Typescript Function with Interface Overloads causes Linter Error

Viewed 14

In VSCode the below function convertColor is giving an error relating to it's IConvertColor interface.

I am using the IConvertColor interface to overload the parameter and return types of the convertColor function.

Code

<script context="module" lang="ts">
// ...
// colors, groupColors, shortColors, and textColors are all string arrays "as const"
type TColor =
    | typeof colors[number] // eg: "is-primary"
    | typeof groupColors[number] // eg: "are-primary"
    | typeof shortColors[number] // eg: "primary"
    | typeof textColors[number]; // eg: "has-text-primary"
interface IConvertColor {
    (color: TColor, prefix: 'default'): typeof colors[number];
    (color: TColor, prefix: 'group'): typeof groupColors[number];
    (color: TColor, prefix: 'short'): typeof shortColors[number];
    (color: TColor, prefix: 'text'): typeof textColors[number];
}
export const convertColor: IConvertColor = (
    color: TColor,
    prefix: 'default' | 'group' | 'short' | 'text',
) => {
    const idx = color.lastIndexOf('-');
    let out = color;
    if (idx !== -1) {
        out = color.slice(idx + 1);
    }
    switch (prefix) {
        case 'default':
            return ('is-' + out) as typeof colors[number];
        case 'group':
            return ('are-' + out) as typeof groupColors[number];
        case 'short':
            return out as typeof shortColors[number];
        case 'text':
            return ('has-text-' + out) as typeof textColors[number];
    }
};
// ...
</script>

Error

Type '(color: TColor, prefix: 'default' | 'group' | 'short' | 'text') => "" | "is-primary" | "is-link" | "is-info" | "is-success" | "is-warning" | "is-danger" | "is-light" | "is-dark" | "are-primary" | "are-link" | "are-info" | ... 20 more ... | "has-text-dark"' is not assignable to type 'IConvertColor'.
  Type '"" | "is-primary" | "is-link" | "is-info" | "is-success" | "is-warning" | "is-danger" | "is-light" | "is-dark" | "are-primary" | "are-link" | "are-info" | "are-success" | "are-warning" | ... 18 more ... | "has-text-dark"' is not assignable to type '"" | "is-primary" | "is-link" | "is-info" | "is-success" | "is-warning" | "is-danger" | "is-light" | "is-dark"'.
    Type '"are-primary"' is not assignable to type '"" | "is-primary" | "is-link" | "is-info" | "is-success" | "is-warning" | "is-danger" | "is-light" | "is-dark"'.ts(2322)

To the best of my knowledge I have used this interface correctly. I could write this as 4 different functions but that'd be a lot to import, and were this JS it'd be unnecessary.

The function itself runs totally fine and even has the desired intellisense when called with different parameters.

What can I do to fix the error? Why is it occurring?

I have tried

  • converting convertColor to a function (from arrow function)

    This did remove the error but does not answer the question. See https://stackoverflow.com/a/73789274/12425097 for how that was written.

  • changing parameter and return types in convertColor

1 Answers

This solution is very much not ideal, but the error goes away when in the regular function format:

type TColor =
    | typeof colors[number]
    | typeof groupColors[number]
    | typeof shortColors[number]
    | typeof textColors[number];
export function convertColor(color: TColor, prefix: 'default'): typeof colors[number];
export function convertColor(color: TColor, prefix: 'group'): typeof groupColors[number];
export function convertColor(color: TColor, prefix: 'short'): typeof shortColors[number];
export function convertColor(color: TColor, prefix: 'text'): typeof textColors[number];
export function convertColor(
    color: TColor,
    prefix: 'default' | 'group' | 'short' | 'text',
) {
    const idx = color.lastIndexOf('-');
    let out;
    if (idx === -1) {
        out = color;
    } else {
        out = color.slice(idx + 1);
    }
    switch (prefix) {
        case 'default':
            return ('is-' + out) as typeof colors[number];
        case 'group':
            return ('are-' + out) as typeof groupColors[number];
        case 'short':
            return out as typeof shortColors[number];
        case 'text':
            return ('has-text-' + out) as typeof textColors[number];
    }
};

This answer does not solve the question, but should help anyone blocked by the same problem.

Related