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

Compiler error unhelpful #17224

Closed
SimonMeskens opened this issue Jul 15, 2017 · 5 comments
Closed

Compiler error unhelpful #17224

SimonMeskens opened this issue Jul 15, 2017 · 5 comments

Comments

@SimonMeskens
Copy link

TypeScript Version: 2.4.1

Code

interface HKT<URI, A> {
  readonly _URI: URI
  readonly _A: A
}

interface URI2HKT<A> {
  "Test": Test<A>
}

type HKTS = keyof URI2HKT<any>;

type HKTTest<URITest extends HKTS, A, B extends HKT<URITest, A>> = B;

// Type '"Test"' is not assignable to type URIHKTof
type HKTof<URIHKTof extends HKTS, A> = HKTTest<URIHKTof, A, URI2HKT<A>[URIHKTof]>;

class Test<A> {
  readonly _A: A
  readonly _URI: "Test"
}

I think this code should typecheck, but it doesn't. If it's not a bug in the code, the compiler error is clearly wrong, so either this is a bug with the typechecker or the error it gives is wrong.

This specific code is all that stops higher kinded types from being completely typesafe in TypeScript, so it'd be a really useful feature.

@SimonMeskens
Copy link
Author

I have a fix for this, that uses another method, but I'm still quite curious why this gives an error.

@ahejlsberg
Copy link
Member

@SimonMeskens Here's a simpler example that demonstrates the issue:

function foo<T extends "Test">() {
    let x: T = "Test";  // Error, "Test" is not assignable to T
}

Given a type parameter T with a constraint C, T is known to be a subtype of C. Therefore, T is assignable to C, but not the other way around. However, in cases where C is a unit type, we effectively know that T and C are idential (because the only possible argument for T is C), but we don't currently take that into account.

@SimonMeskens
Copy link
Author

I don't think that's the error here actually, as this code works:

type HKTof<URIHKTof extends HKTS, A> = URI2HKT<A>[URIHKTof];

Which does exactly the same constrained parameter indexing the exact same class.

@ahejlsberg
Copy link
Member

No, I think it boils down to what I said above. This simplification also fails:

type HKTof<URIHKTof extends HKTS, A> = HKTTest<URIHKTof, A, Test<A>>;

Here the third type argument to HKTTest fails the constraint check because the _URI property has type URIHKTof in the constraint and type "Test" in the type argument, where URIHKTof is a type parameter with the constraint "Test", which is a unit type (but we don't take that into account).

@SimonMeskens
Copy link
Author

Interesting, thanks, I think I understand a little better now. The type system is so powerful, it's hard to reason about these complex structures sometimes. It almost turns into write-only code. Luckily we can bury code like this in libraries, so they don't face the user.

@SimonMeskens SimonMeskens reopened this Jul 17, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants