-
Notifications
You must be signed in to change notification settings - Fork 22
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
Conditional types #29
Comments
There are a few things going on here, first... // `string` is not correct here
expectType<string>(R.defaultTo('This file', undefined)); // error
// `string | undefined` is
expectType<string | undefined>(R.defaultTo('This file', undefined)); // ok!
// `undefined` is taken literally above, no differently than how the return type is `string | number` for this
expectType<string | number>(R.defaultTo('This file', 123)); // ok! Your typescript playground example is much more interesting though R.compose(
R.defaultTo("This file"), // :(
R.nth(1),
R.match(/.*\.(.*)/),
R.propOr("", "name")
) The main error that you get is
I'm pretty sure that that error is specifically because the function that If you remove R.compose(
R.defaultTo("This file"), //
R.match(/.*\.(.*)/),
R.propOr("", "name")
) Once called, the return type is now See playground This is just one of those situations where typescript inference breaks down. The only way I know how to fix this is to add another overload to export function defaultTo<T, U>(a: T, b: U | null | undefined): T | U;
// new overload that lets you set `U` ahead of time
export function defaultTo<T, U>(a: T): (b: U | null | undefined) => T | U;
export function defaultTo<T>(a: T): <U>(b: U | null | undefined) => T | U; |
Cool! That's interesting about the expectType<string | undefined>(R.defaultTo('This file', undefined)); // << incorrect If I'm not mistaken, the above is incorrect. Given a default value of I've come up with some new definitions using conditional types that I think satisfy the correct behavior of export function defaultTo<Default, Value>(a: Default, b: Value): (Value extends (null | undefined) ? Default | NonNullable<Value> : Value);
export function defaultTo<Default>(a: Default): <Value>(b: Value) => (Value extends (null | undefined) ? Default | NonNullable<Value> : Value); Here are some tests for expectType<string>(defaultTo('default value', undefined));
expectType<string>(defaultTo(0, 'two'));
expectType<number>(defaultTo('zero', 2));
const numberOrUndefined = Math.random() < 0.5 ? 0 : undefined;
expectType<string | number>(defaultTo('default value', numberOrUndefined)); This seems to be working correctly. Does this look correct to you? (Here's the code if you want to take a look) |
Hello!
I've been messing around with my example and I think I've narrowed the issue down to the fact that the following doesn't work:
Here are the type definitions:
I think the problem stems from the result type being
T | U
, which in this case would includeundefined
. I think we need to somehow use conditional types or something to make the types more aware about how the function behaves.I assume this would be a problem for a bunch of other types too, like
propOr
, etc.I don't know much about conditional types and I'm going to read those docs and do more research tomorrow, but I just wanted to post this to see if anyone else has any insight into this issue!
The text was updated successfully, but these errors were encountered: