Skip to content
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

Type 'K' is not assignable to type 'V (extends K)' #29397

Closed
kripod opened this issue Jan 13, 2019 · 3 comments
Closed

Type 'K' is not assignable to type 'V (extends K)' #29397

kripod opened this issue Jan 13, 2019 · 3 comments

Comments

@kripod
Copy link

kripod commented Jan 13, 2019

TypeScript Version: 3.3.0-dev.20190112

Search Terms: type generic is not assignable to type generic extends generic

Code

export const defaultTo = <T, U>(value: T, defaultValue: U) =>
  value == null ? defaultValue : value;

export const propOr = <
  K extends number | string,
  V extends K,
  T extends { [key in K]: V }
>(
  object: T,
) => (key: K, defaultValue: V = key) =>
  key == null ? defaultValue : defaultTo((object || {})[key], defaultValue);

tsconfig.json

{
  "compilerOptions": {
    "jsx": "react",
    "target": "esnext",
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "strict": true
  },
  "include": ["src/**/*"]
}

Expected behavior:

defaultValue: V = key should work without errors (even in strict mode).

Playground Link: http://www.typescriptlang.org/play/#src=export%20const%20defaultTo%20%3D%20%3CT%2C%20U%3E(value%3A%20T%2C%20defaultValue%3A%20U)%20%3D%3E%0D%0A%20%20value%20%3D%3D%20null%20%3F%20defaultValue%20%3A%20value%3B%0D%0A%0D%0Aexport%20const%20propOr%20%3D%20%3C%0D%0A%20%20K%20extends%20number%20%7C%20string%2C%0D%0A%20%20V%20extends%20K%2C%0D%0A%20%20T%20extends%20%7B%20%5Bkey%20in%20K%5D%3A%20V%20%7D%0D%0A%3E(%0D%0A%20%20object%3A%20T%2C%0D%0A)%20%3D%3E%20(key%3A%20K%2C%20defaultValue%3A%20V%20%3D%20key)%20%3D%3E%0D%0A%20%20key%20%3D%3D%20null%20%3F%20defaultValue%20%3A%20defaultTo((object%20%7C%7C%20%7B%7D)%5Bkey%5D%2C%20defaultValue)%3B

@jack-williams
Copy link
Collaborator

jack-williams commented Jan 13, 2019

The error message is correct here, but the error could be improved and this is tracked by #29049.

The reason why the error is correct is because key is only known to satisfy the constraint of V, but key might not satisfy V itself. In other words, key is assignable to the upper bound of V, but for this to be safe you need key to be assignable to all instantiations of V, which you don't know.

A concrete example:

function example<T extends number>(x: T = 10) {
    return;
}

example<3>();

The value 10 is assignable to the constraint of T, but it is not assignable to this particular instantiation of T. If there was no error I would passing 10 where 3 is expected!

Your example is essentially the same, except with an intermediate type variable; the same idea applies transitively though.

function example2<T extends number, U extends T>(x: T, y: U = x) {
    return;
}

example2<number, 3>(10);

@kripod
Copy link
Author

kripod commented Jan 13, 2019

@jack-williams Thank you for the explanation, I'm closing this issue.

@kripod kripod closed this as completed Jan 13, 2019
@jack-williams
Copy link
Collaborator

@kripod No problem!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants