Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Does typescript automatically accept undeclared subtypes as function arguments?

I’m passing an object of type TestInput into a method quadrant that is expecting an argument of type CoordinatesMeta.

So this is the method:

quadrant(c:CoordinatesMeta) {}

The TestInput type has all the properties that CoordinatesMeta has.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Do we need to declare to Typescript that calling:

quadrant(t) // t has TestInput type

Should be OK, because t has all the required properties?

This is a minimal reproducible example:

interface Center {
  x: number;
  y: number;
}

interface MetaCoordinates {
  x: number;
  y: number;
  c: Center;
}

declare function quadrant(MC: MetaCoordinates): number; 

interface TestInput {
  x: number;
  y: number;
  c: Center;
  q: number;
}
const c: Center = Object.freeze({ x: 100, y: 100 });
const input: TestInput = { x: 99, y: 100, c, q: 1 };

console.log(quadrant(input));

Stackblitz link

and it runs without errors, so I just wanted to make sure I’m getting the semantics right?

>Solution :

You got it right. The TypeScript documentation of interfaces explains it in the first paragraph:

An interface declaration is another way to name an object type:

interface Point {
  x: number;
  y: number;
}

function printCoord(pt: Point) {
  console.log("The coordinate's x value is " + pt.x);
  console.log("The coordinate's y value is " + pt.y);
}

printCoord({ x: 100, y: 100 });

Just like when we used a type alias above, the example works just as if we had used an anonymous object type. TypeScript is only concerned with the structure of the value we passed to printCoord – it only cares that it has the expected properties. Being concerned only with the structure and capabilities of types is why we call TypeScript a structurally typed type system.

Applied to your code, this means that as long as the type of input has all required properties of type MetaCoordinates, with the same (or compatible) types, the function quadrant() accepts input as argument.

This is just a particular type of assignment. Any object of type TestInput can be assigned to a variable of type MetaCoordinates because it has all the properties of type MetaCoordinates and some extra properties that the type MetaCoordinates does not know and does not care about.

Returning a value from a function, storing the value returned by a function are other examples of assignments. All of them allow to put a richer object into a variable of a type with less properties.

The types of the properties must be the same or the properties must be assignable as discussed here. However, it does not allow to use an object literal with excess properties to initialize a variable of some type.

This is rejected:

const mc: MetaCoordinates = { x: 99, y: 100, c, q: 1 };

But this is perfectly fine:

const input: TestInput = { x: 99, y: 100, c, q: 1 };
const mc: MetaCoordinates = input;
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading