Giter VIP home page Giter VIP logo

Comments (2)

lax4mike avatar lax4mike commented on June 19, 2024 1

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.

Harris-Miller avatar Harris-Miller commented on June 19, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.