0

I'm stilling learning the intricacies of typescript.

While trying to figure out Typescript: Generic to specific type , I came upon another situation I don't understand how Typescript is resolving.

export type GenericType = {
    [key: string]: {
      prop1: string,
      prop2?: string,
      prop3?: number,
  }
};
const GoodObj: GenericType = {
  key1: {
    prop1: "hi",
    // prop5: "what", // Type '{ prop1: string; prop5: string; }' is not assignable to type '{ prop1: string; prop2?: string; prop3?: number; }'.
  },
  key2: {
    prop1: "bye",
    prop2: "sup",
  },
};

console.log(GoodObj);

const BadObj = {
  key1: {
    prop1: "hi",
    prop5: "what",
  },
  key2: {
    prop1: "bye",
    prop2: "sup",
  },
};

const BadObjGen: GenericType = BadObj;

console.log(BadObjGen);

In the above example, typescript will complain if I put an invalid prop into GoodObj like I did to BadObj. However, BadObj doesn't complain when I assign an invalid obj to to BadObjGen.

Yet, if I did the same thing with primitives, it does complain.

const type1: number = 1;
const type2: string = type1; // Type 'number' is not assignable to type 'string'

Under what circumstances does Typescript type check objects?

Codesandbox - https://codesandbox.io/s/typescript-experiment-hp92o?file=/src/index.ts:175-316

SILENT
  • 3,916
  • 3
  • 38
  • 57
  • 3
    [Excess property checks](https://www.typescriptlang.org/docs/handbook/interfaces.html#excess-property-checks) – VLAZ Sep 01 '20 at 06:24
  • `const BadObjGen: GenericType = BadObj;` is the same as `const BadObjGen = BadObj as GenericType;` which is basically telling ts to force convert the type, and object can be force converted to another object, but two basic types, number and string is not convertible. – arslan2012 Sep 01 '20 at 06:25
  • See also: [How excess property check helps?](https://stackoverflow.com/q/50143250) | [Why can I avoid excess property check in typescript just by passing a reference to an object to a function rather than the object in its literal form?](https://stackoverflow.com/q/52852278) – VLAZ Sep 01 '20 at 06:26

1 Answers1

0

This is because interfaces are not limited to specific properties: An object must have the properties defined in the interface but is allowed to have more. A smaller example to demonstrate you would be:

interface a {
    x: number;
}

const l = {
    x: 1,
    y: 2
}

const test: a = l; //valid as l has a x: number property, although it also has y: number

//Note: this will throw an error in TS, even though it exists, because you typed it as having only a x-property
test.y = 5; //error
Zer0
  • 1,580
  • 10
  • 28