I want to expose a method that takes some Union type as parameter and provides autocompletion for that. As this union type could be extended via declaration merging, autocompletion is a key feature here.
But in cases where the user doesn't use TypeScript when using my library, or does not want to add particular typings to the declaration, it should alternatively accept a string
alternatively to the union type.
In short: I want autocompletion for the union type, but also allow any string that does not match it.
Example with only the union type:
export interface Values {
'variant-a': undefined,
'variant-b': undefined,
'variant-c': undefined,
}
function doAThing<T extends keyof Values>(name: T): void {
console.log(name);
}
Things I tried:
function doAThing<T extends keyof Values>(name: string): void;
- does merge types with keyof Values
, and becomes string for both then. No autocompletion.string
: <T extends keyof Values | string>
- merges to only string
. No autocompletion as well.I found a solution here:
export type Values = {
'variant-a': undefined,
'variant-b': undefined,
'variant-c': undefined,
}
type AnyString<T> = T | (string & {});
function doAThing<T extends keyof Values>(name: AnyString<T>): void {
console.log(name);
}
doAThing('variant-b'); // Autocompleted
doAThing('variant-d'); // Not autocompleted, but still accepted