Comments (2)
Cool! That's interesting about the nth
. I'll dig into that in a bit. Right now, I'd like to focus on defaultTo
because I think the type definition is wrong.
expectType<string | undefined>(R.defaultTo('This file', undefined)); // << incorrect
If I'm not mistaken, the above is incorrect. Given a default value of 'This file'
, defaultTo
will never return undefined
. The correct return type for this is string
.
I've come up with some new definitions using conditional types that I think satisfy the correct behavior of defaultTo
:
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 defaultTo
that pass:
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)
from types.
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
Argument of type '<T extends string | readonly any[]>(list: T) => (T extends (infer E)[] ? E : string) | undefined' is not assignable to parameter of type '(a: string[]) => U | null | undefined'.
Type 'string | undefined' is not assignable to type 'U | null | undefined'.
Type 'string' is not assignable to type 'U'.
'U' could be instantiated with an arbitrary type which could be unrelated to 'string'.
I'm pretty sure that that error is specifically because the function that nth
returns returns (T extends (infer E)[] ? E : string) | undefined
. And the problem here is that the actual return of that returned function is not something that U
can determine because of the infer
If you remove R.nth
it works
R.compose(
R.defaultTo("This file"), //
R.match(/.*\.(.*)/),
R.propOr("", "name")
)
Once called, the return type is now string | string[]
as expected. This is because R.match
ends with the strict type string[]
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 defaultTo
that lets you set T
and U
yourself. See playground
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;
from types.
Related Issues (17)
- @types/ramda parity HOT 1
- How to type curried functions HOT 3
- mergeDeepLeft behaves differently than in @types/ramda HOT 4
- The Master List
- mergeAll does not accept arrays anymore HOT 2
- 0.29.2 breaks tests on DT HOT 2
- What to do about transducers
- transduce's accumulator type
- `pluck` does not work with argument typed as `any` HOT 2
- `assoc` returns a narrower type than what is passed HOT 2
- `of` now receives two parameters instead of one HOT 2
- Github Actions and npm publish HOT 1
- Clean up `tools.d.ts`
- addIndex
- Automate release HOT 2
- MR template and merge requirements HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from types.