1

So I have the following code sample:

interface MyInterface<T> {
  myFunc(value: T): void;
}

class MyImplementation implements MyInterface<number> {
  myFunc(value: number): void {
    console.log(value / 2);
  }
}

function myTest(): MyInterface<number|string> {
  return new MyImplementation(); // doesn't look quite right
}

myTest().myFunc("I am not a number"); // outputs NaN

I can't quite get my head around why typescript is allowing me to return MyImplementation in place of MyInterface<number | string>. I understand we want number to be assignable to number | string but surely not for generic parameters.

1 Answer 1

1

This example also works without generics:

interface MyInterface {
  myFunc(value: number): void;
}

interface MyInterface2 {
  myFunc(value: number|string): void;
}

class MyImplementation implements MyInterface {
  myFunc(value: number): void {
    console.log(value / 2);
  }
}

function myTest(): MyInterface2 {
  return new MyImplementation(); // doesn't look quite right
}

myTest().myFunc("I am not a number"); // outputs NaN

Typescript was designed to have some unsoundness in the type system as described here: https://www.typescriptlang.org/docs/handbook/type-compatibility.html

To work around this, you can define your interface like this:

interface MyInterface<T> {
  myFunc: (value: T) => void;
}

And then enable strictFunctionTypes or strict in your tsconfig.json.

See also: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-6.html

The stricter checking applies to all function types, except those originating in method or constructor declarations. Methods are excluded specifically to ensure generic classes and interfaces (such as Array) continue to mostly relate covariantly.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the crystal clear answer. Declaring the function as a property rather than a method did the trick having already --strict enabled in my typescript config.

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.