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
Discriminated union expands boolean to Foo<true> | Foo<false> instead of Foo<boolean> #46518
exportinterfaceObservableBase<T>{(): T;// Read the current value(newValue: T): void;// Write a new valuevalue: T;}exporttypeObservable<T>=Textendsany[] ? ObservableArray<T> : ObservableBase<T>;interfaceObservableArray<Textendsany[]>extendsObservableBase<T>{/** Array push. */push: (arg: T[number])=>void;}functionmakeObservable<T>(initial: T): Observable<T>{return{value: initial,}asObservable<T>;}constx=true;constobs=makeObservable(x);exportfunctionfoo(z: boolean){obs(z);// write a new value (should be `(boolean) => void`)obs();// read the current value (should be `() => boolean`)}
🙁 Actual behavior
No overload matches this call.
Overload 1 of 3, '(newValue: false): true | void', gave the following error.
Argument of type 'boolean' is not assignable to parameter of type 'false'.
Overload 2 of 3, '(newValue: true): false | void', gave the following error.
Argument of type 'boolean' is not assignable to parameter of type 'true'.
Note that obs has a type of ObservableBase<false> | ObservableBase<true>. This doesn't seem right to me. I made an observable that could accept values of true or false, not an observable that only accepts true or an observable that only accepts false.
I was sure I remember seeing something in the TypeScript documentation that allowed a bit more control over when union types are expanded for generics that would prevent this kind of thing, but I have searched high and low and cannot find anything.
If you change makeObservable to return an ObservableBase<T> instead of an Observable<T> then obs correctly gets a type of ObservableBase<boolean> and everything works. But the discriminated union seems to break everything.
Activity
nmain commentedon Oct 25, 2021
This is what you were looking for, Distributive Conditional Types:
https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types
The fix in your code:
https://www.typescriptlang.org/play?#code/KYDwDg9gTgLgBASwHY2FAZgQwMbDgeQCMBnNAN00IBtgAhTUgHgBUA+OAbwCg5e4AKAJQAuOMwDcPPvyTAA7gDVMVAK7BRzEXDIQEAE0l9tytRskBfLl1CRYcGAE8weIqSgVqwFuwC8cANrMALpwoKhIesQBmEgO-kEhAPwEJOSUNACCUFCYDt5woq5pnvRMbJJcyKgYOC6p7unAWTl5zKEg4ZFwMXFB7GHAEVFFDSUMXmycUrwA9ABUc3DNuXBgKsQAFgB0cHMz06vrG6L8mFAA5hr+SCoAtoRoQYJwPuw6+hZW6CpI2DAIECQcFumAA1sARh4aN5+MgEP9lBotJDGvluEYoMAYCooED0UY+BRVOpEEh4QhlAAaA7mbrDepQiasT5cbCA4jwEAvexQNSSNlIDlwCAkbkg8Eozz8ECCCo2aDwb6-f6AuDoCAQfgAL1EhA1NBiz3xvBFxG1soOpqEnyAA
SystemParadox commentedon Oct 25, 2021
Aha! Yes that's exactly what I was looking for! Thanks.