You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Using undefined as a discriminator within a mapped type yields erroneous types when primitive intersections are involved #14471
// A *self-contained* demonstration of the problem follows...typeDeepReadonly<T>={readonly[KinkeyofT]: DeepReadonly<T[K]>;}interfaceFieldBrand{" do not use ": void;}typeFieldId=number&FieldBrand;interfaceDefOne{field: string|FieldId;kind: string;}interfaceDefTwo{field?: undefined;// Allow discriminant checks on 'field'value: string;}typeDef=DefOne|DefTwo;interfaceState{a?: Def;b?: Def;}typeROState=DeepReadonly<State>;functionlookupName(f: FieldId): string{return"";}functionremapFieldsToNames(channels: ROState): ROState{constnewState: State={};for(constkofObject.keys(channels)){constkey=kaskeyofROState;constch=channels[key];letreplacement: ROState[typeofkey]|undefined=undefined;if(ch){if(ch.field){constf=ch.field;if(typeoff==="number"){f;// Should be FieldId or number, not never!replacement={ ...ch,field: lookupName(f)};}elseif(typeoff==="string"){f;// correct}}}newState[k]=replacement||channels[k];}returnnewState;}
Expected behavior:
There are no type errors in the above, and f after the typeof f === "number" check is either a number or FieldId.
Actual behavior: replacement = { ...ch, field: lookupName(f) }; has a type error and f is of type never.
There's also some odd shenanigans going on with DeepReadonly leaving off its generic arguments in the quickinfo within the function body which may be related/should be looked into:
The weirdness with DeepReadonly and a tagged number actually cause a type incombatibility every time I try to assign the deeply readonly structure to the normal one.
Activity
weswigham commentedon Mar 5, 2017
There's also some odd shenanigans going on with

DeepReadonlyleaving off its generic arguments in the quickinfo within the function body which may be related/should be looked into:weswigham commentedon Mar 5, 2017
The weirdness with
DeepReadonlyand a tagged number actually cause a type incombatibility every time I try to assign the deeply readonly structure to the normal one.denis-migdal commentedon Apr 8, 2026
Isn't the issue on the
DeepReadonlytype definition ?Using the following type definition seems to solves this issue on the last TS version:
Cf Playground Link