0

I'm trying to solve an issue where I want to chain multiple function calls and also have typescript checking whether I'm linking them together correctly.

export class A<T, K> {
  public foo(a: A<K, T>): A<K, T> {
    return a;
  }
}

const a1 = new A<string, number>();
const a2 = new A<string, number>();

a1.foo(a2); // does not show an error

When I hoover over method calls I see correct declaration. What am I missing here?

1 Answer 1

1

Typescript uses a structural type system. If you don't use type parameters they don't much matter. In your case you do use the type parameters, but in a recursive way. This will probably mean the compiler will check the parameters for a while but will not manage to find a definite incompatibility between A<string, number> and A<number, string> so it will asume they are compatibile.

Typescript uses a pragmatic approach to a type system. It should be useful most of the time while modeling the structural behavior of Javascript. Most of the time this works well, you just found one of the corner cases where this gives some surprising results. (I hesitate to say it gives a wrong result, because I can't think of a runtime error this admittedly surprising type compatibility will cause)

The good news is that this behavior goes away as soon as you add a member that uses any of the type parameters in a more direct way:

export class A<T, K> {
    private k!:K
    public foo(a: A<K, T>): A<K, T> {
        return a;
    }
}

const a1 = new A<string, number>();
const a2 = new A<string, number>();

a1.foo(a2); // error
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.