Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mix index signature with known properties?

Let's say the interface has some known properties with their types, and can have additional ones with unknown keys and some other types, something like:

interface Foo {
  length: number;
  [key: string]: string;
}

const foo : Foo = {
  length: 1,
  txt: "TXT",
};

TS error:

Property 'length' of type 'number' is not assignable to string index type 'string'.

How should such an interface be typed?

like image 363
user2520818 Avatar asked Aug 15 '20 19:08

user2520818


2 Answers

[key: string]: string; this prevents the Foo interface to have none string properties (in your example, number).

What you can do is to separate the known and unknown properties in two interfaces and define your target type as a union type like below:

interface Foo {      
  length: number;
}

interface Bar {
    [key: string]: string ;
}

type FooBar = Foo | Bar;

const foo : FooBar = {
  length: 1, // its ok defined in foo
  txt: "TXT", // string is ok
  baz : 3 // error because its not string
};

Playground Link

like image 196
Eldar Avatar answered Nov 15 '22 07:11

Eldar


Check out this snippet it explain the point well

interface ArrStr {
  [key: string]: string | number; // Must accommodate all members

  [index: number]: string; // Can be a subset of string indexer

  // Just an example member
  length: number;
}

You can check this article for more details (i picked the snippet from there)

https://basarat.gitbook.io/typescript/type-system/index-signatures

For this element

Having both string and number indexers
This is not a common use case, but TypeScript compiler supports it nonetheless. However, it has the restriction that the string indexer is more strict than the number indexer. This is intentional e.g. to allow typing stuff like:

like image 22
Mohamed Allal Avatar answered Nov 15 '22 07:11

Mohamed Allal