question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Assignability rule for conditional types needs to require check types and distributivity to be identical

See original GitHub issue

TypeScript Version: master (e4718564e5b2c1f2e7bbef27fc480fd8172dfdc0)

Search Terms: assignable assignability conditional type check type checkType distributive distributivity identical unsound

Code

type MyElement<A> = [A] extends [[infer E]] ? E : never;
function oops<A, B extends A>(arg: MyElement<A>): MyElement<B> { 
    return arg;  // compiles OK, expected compile error
}
oops<[number | string], [string]>(42).slice();  // runtime error

type MyAcceptor<A> = [A] extends [[infer E]] ? (arg: E) => void : never;
function oops2<A, B extends A>(arg: MyAcceptor<B>): MyAcceptor<A> { 
    return arg;  // compiles OK, expected compile error
}
oops2<[number | string], [string]>((arg) => arg.slice())(42);  // runtime error

type Dist<T> = T extends number ? number : string; 
type Aux<A extends { a: unknown }> = A["a"] extends number ? number : string;
type Nondist<T> = Aux<{a: T}>;
function oops3<T>(arg: Dist<T>): Nondist<T> {
    return arg;  // compiles OK, expected compile error
}
oops3<number | string>(42).slice();  // runtime error

Expected behavior: Compile errors as marked.

Actual behavior: Compiles OK, runtime errors as marked.

Playground Link: link

Related Issues: None found

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:15 (11 by maintainers)

github_iconTop GitHub Comments

1reaction
jack-williamscommented, Oct 13, 2018

@jcalz @mattmccutchen Related to that issue: #27470. (I’ll leave the discussing of this issue at that as I don’t want to go off topic).

1reaction
mattmccutchencommented, Sep 25, 2018

@jack-williams Assuming the conditional types are non-distributive (sigh), you are close. We may want to account for nontransitivity of assignability. For example, consider:

function foo<A, B extends A>(arg: A extends number ? {} : never):
    B extends number ? {} : never {
    return arg;
}
let n: never = foo<any, string>({});

I suspect the concept we would need may be similar to the “definitely assignable” relation that is used to evaluate conditional types. Or we could just say that anyone who writes the above code deserves what they get.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Documentation - Conditional Types - TypeScript
Create types which act like if statements in the type system.
Read more >
Conditional types in TypeScript - Artsy Engineering
TypeScript is happy treating two completely unrelated classes as equivalent because they have the same structure and the same capabilities.
Read more >
Is `distributive conditional types` the desired behavior typically ...
Yes, distributivity over unions happens in multiple type operations, as shown. But not every type function is distributive... for example, you ...
Read more >
TypeScript: Conditional Types Explained - Ross Bulat - Medium
Conditionals are often coupled with generic types (otherwise termed type parameters) to test whether such parameter meets a certain condition.
Read more >
TypeScript Berlin Meetup #8 - Distributive conditional types
In this talk, Iván will delve into distributive conditional types and what they are good for, as an example of how thinking of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found