-1

I'm learning TypeScript programming, but I don't understand why a type can accept a subtype when used as a function parameter. I think the code below should give an error but it doesn't:

type Numbers = { x: number, y: number };
function add(arg: Numbers) {
  return arg.x + arg.y;
}

type NumbersWithName = Numbers & { name: string }
const numbersWithName: NumbersWithName = { name: 'alice', x: 0, y: 1 };
add(numbersWithName); // No Error

const numbers: Numbers = { name: 'alice', x: 0, y: 1 }; // Error

If the logic in the add function does not welcome others attributes, what should I do? Is it unreasonable to do so?

KInGcC
  • 372
  • 1
  • 2
  • 9
  • Your question is based on a false premise; `NumbersWithName` is a subtype, not a supertype. – kaya3 Mar 10 '21 at 09:36
  • @kaya3 Thanks for reminding! Has been corrected – KInGcC Mar 10 '21 at 09:56
  • That's just how Typescript works. It only checks for excess properties when defining object literals. – Roberto Zvjerković Mar 10 '21 at 10:08
  • In *every* language, you can call a function with an argument whose type is a subtype of the parameter type; you can always use a subtype's value whereever its supertype's value is allowed. That is the whole point of subtypes. I don't see how there is a question here. – kaya3 Mar 10 '21 at 12:02

2 Answers2

0

This is because TypeScript has structural type system.

See next example:

type Numbers = { x: number, y: number };

function add(arg: Numbers) {
    return arg.x + arg.y;
}

type NumbersWithName = Numbers & { name: string }

type Allowed = NumbersWithName extends Numbers ? true : false // true

const numbersWithName: NumbersWithName = { name: 'alice', x: 0, y: 1 };
add(numbersWithName); // no error,

// see https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks
add({ name: 'alice', x: 0, y: 1 }) // error

You can force compiler error by using object literal instead of passing a reference to object.

See this answer

See this open issue and another one possible workaround

  • This is not really to do with structural types, the issue is that OP thinks it's a supertype when really it is a subtype. – kaya3 Mar 10 '21 at 09:39
0

This is actually a question about Covariance_&_Contravariance.

The arguments to TypeScript function are covariant, so subtype can be used as supertype.

Read this:

KInGcC
  • 372
  • 1
  • 2
  • 9