-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Extract
not narrowing type union in mapped type passed as generic
#57827
Comments
Conditional types are tricky as they often stay deferred in generic contexts. This version could somewhat easily work though (and it doesn't): type StringKeys<T> = keyof {
[P in keyof T as T[P] extends string ? P & string : never]: any;
};
const bloop = <T,>(z: StringKeys<T>) => {
const f: string = z; // errors but shouldnt
}; As a workaround, you can use this version: type StringKeys<T> = keyof {
[P in keyof T as T[P] extends string ? P : never]: any;
} &
string;
const bloop = <T,>(z: StringKeys<T>) => {
const f: string = z;
}; |
That workaround works in my real codebase, so I'll cut over to that approach for now - is this a matter of the intersection (instead of |
I would guess itβs just a matter of the compiler knowing that |
Bisects to #56742 |
Not sure if I should create my own issue but on topic for Extract not narrowing union with generics type Example = { case: '1', value: number } | { case: '2', value: string } | { case: '3', value: boolean }
function test<T extends Pick<Example, 'case'>>(field: T['case']): Extract<Example, T> {
switch(field) {
case '1': {
return { case: '1', value: 1 };
}
case '2': {
return { case: '2', value: 'string'};
}
case '3': {
return { case: '3', value: true };
}
default:
throw new Error()
}
} Tried with a lot of versions (v5.5.4 and nightly for examples) |
I'm not entirely sure if this is the same issue, but here is the code that is affected in my case. It results in a compilation error starting from 5.4.x. const data = {
1: { id: 1, name: "1" },
2: { id: 2, name: "2" },
3: { id: 3, name: "3" },
4: { id: 4, name: "4" },
5: { id: 5, name: "5" },
6: { id: 6, name: "6" },
7: { id: 7, name: "7" },
8: { id: 8, name: "8" },
9: { id: 9, name: "9" }
} as const;
type Ids = keyof typeof data
type Data = typeof data[keyof typeof data]
const someExtraData = {
3: {}, 5: {}, 7: {}, 8: {}, 9: {}
} as const satisfies Partial<Record<Ids, {}>>;
type SomeIds = keyof typeof someExtraData
type SomeData<I extends SomeIds> = Extract<Data, { id: I }>
function foo<I extends SomeIds>(value: SomeData<I>) {
// Property 'id' does not exist on type 'SomeExtraData<I>'.
// Property 'id' does not exist on type 'Extract<{ readonly id: 1; readonly name: "1"; }, { id: I; }>'.(2339)
value.id;
} Update: The workaround code for my case is as follows: type SomeIds = keyof typeof someExtraData
type SomeData<I extends SomeIds> = Extract<typeof data[SomeIds], { id: I }>
function foo<I extends SomeIds>(value: SomeData<I>) {
const id: I = value.id;
} |
π Search Terms
Extract, type union
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play?ts=5.4.2#code/C4TwDgpgBAysBOBLAdgcwNIRAZwDwBUA+KAXigFEAPBAQwGNhcBrLAewDMoBvAWACgogqAG0AClBRQWIDlHxQa2OWIC6UCNQjIAJkuwIUqKAH4oogFxRkEAG4R4KyzWQh+AXwA0UfUjSF+-HSsyPpQAEYANqysYKRQBB6EABQAXpZwvhhYeEQAlKTEvAJQQSHAUOyWPoZxKe4BfCjA9uz00Ira3PyCAI4A7hBVBmj1fPwREOU06cNZOLgd-nxAA
π» Code
π Actual behavior
z
is not assignable tostring
in thebloop
functionπ Expected behavior
z
should be assignable tostring
, because we extract string-extending keysAdditional information about the issue
This was working just fine on 5.3.3, and continues to work when the generic is concretized (hence the
let
at the bottom of the example)The text was updated successfully, but these errors were encountered: