TypeScript Version: 4.0.0-dev.20200531
Search Terms: type narrow discriminant generic
Code
interfaceA<T,KextendskeyofT>{t: true;v: T[K];}interfaceB{t: false;e: Error;}typeX<T>=A<T,keyofT>|B;typeSome={y: number;z: string};declarefunctionassertIsX(x: unknown): asserts x is X<Some>;// CASE 1: narrowing unknown (works)declareconstsome: unknown;assertIsX(some);// Ok, `r1` is `string | number | Error` as expectedconstr1=some.t ? some.v : some.e;// CASE 2: before narrowing (works)declareconstsome2: X<{[k: string]: unknown}>;// Ok, `r2` is `unknown` as expectedconstr2=some2.t ? some2.v : some2.e;// CASE 3: narrowing again (does not work)assertIsX(some2);// ERROR: `some2` narrowed to `B`, not `X<Some>`,// so `v` isn't accesiblesome2.t ? some2.v : some2.e;// CASE 4: narrowing `A<any, any> | B` (does not work)declarefunctiononlyASomeHere(x: A<Some,keyofSome>): void;declareconsta: A<any,any>;// `A<any, any>` is assignable to `A<Some, keyof Some>`onlyASomeHere(a);declareconstsome3: A<any,any>|B;assertIsX(some3);// ERROR: `some3` narrowed to `B`, not `X<Some>`some3.t ? some3.v : some3.e;I'm using a type assertion, but a type predicate makes no difference. The same happens starting with X<any> or X<unknown>.
Expected behavior:some2 is narrowed to the union A<Some> | B so .v can be accessed when t === true.
Actual behavior:some2 narrows only to B, so when t === truesome2 is never.
Playground Link:playground
Related Issues: Maybe #30557 but that case works on last nightly and this does not.
TypeScript Version: 4.0.0-dev.20200531
Search Terms: type narrow discriminant generic
Code
I'm using a type assertion, but a type predicate makes no difference. The same happens starting with
X<any>orX<unknown>.Expected behavior:
some2is narrowed to the unionA<Some> | Bso.vcan be accessed whent === true.Actual behavior:
some2narrows only toB, so whent === truesome2isnever.Playground Link:playground
Related Issues: Maybe #30557 but that case works on last nightly and this does not.