Home > Software engineering >  typescript - a tighter type cannot feed into a looser type?
typescript - a tighter type cannot feed into a looser type?

Time:09-20

const func: (prm: Record<string, string | number>) => void = (prm) => {
    return;
};

interface Obj {
    key1: string;
}

func({ key1: 'value1' } as Obj); // Argument of type 'Obj' is not assignable to parameter of type 'Record<string, string | number>'. Index signature for type 'string' is missing in type 'Obj'.ts(2345)

How come the Obj object cannot feed into the fuction func while Obj can fulfill the prm required data shape?

CodePudding user response:

The application fails because an object of type Record<string, string | number> should have a string | number value for any string key, which is not the case for Obj.

Consider for example this type-correct func definition:

const func: (prm: Record<string, string | number>) => void = (prm) => {
  const v = prm.someProp
  console.log(v.toLocaleString())
};

Given the type of prm, a property prm.someProp should exist (and it should have a toLocaleString method as string and number do). However, if you call func it with an Obj argument, it will fail at runtime:

func({ key1: 'value1' } as any); // Runtime error

You can get the desired type by making func generic:

const func: <K extends string>(prm: Record<K, string | number>) => void = (prm) => {
  return
};

interface Obj {
  key1: string;
}

func({ key1: 'value1' } as Obj); // No type error

TypeScript playground

  • Related