Description
Hello Typescript team!
I've been working on updating my team's typescript codebase from v 3.2.1 to v 3.6.4
I'm having some issues updating my codebase to support the breaking changes, and wanted to start a discussion to see if what I'm coming across is by design, and if so, what is the recommended solution for working through it.
Below I'll create a simplified example of the issue we're having, and I've verified that the issue only appears after and including Typescript 3.5. I believe the issue may be related to this:
interface StoreParams {
key1: string;
key2: number;
key3: string[];
}
function get<Key extends keyof StoreParams>(key: Key): StoreParams[Key] | null {
const key1Return: string = 'key1Return';
const key2Return: number = 2;
const key3Return: string[] = ['a', 'b', 'c'];
if (key === 'key1') {
return key1Return;
}
if (key === 'key2') {
return key2Return;
}
if (key === 'key3') {
return key3Return;
}
return null;
}
The above code results in an error in each of the key return statements, respectively they are:
Type 'string' is not assignable to type 'StoreParams[Key] | null'.
Type 'number' is not assignable to type 'StoreParams[Key] | null'.
Type 'string[]' is not assignable to type 'StoreParams[Key]'.
Type 'string[]' is not assignable to type 'never'.
It seems in each of the return statements, the return type is still StoreParams[Key] | null
, where Key
has not been filtered down after the if
statement which normally acts as a type guard for key
.
If I replace the generic Key
with just keyof StoreParams
, the type guards seem to work on key
, but I've lost the benefit of the generic in that I'm still just returning StoreParams[keyof StoreParams]
, meaning in each of the return statements I can return string | number | string[] | null
.
Any help or advice would be greatly appreciated, and huge shoutout to the team for this immensely useful tool!