Typescript przypisujący interfejs lub typ do Record <string, string>

Nov 23 2020

Po przeczytaniu tego pytania lub tego artykułu nadal jestem trochę zdezorientowany co do subtelnych różnic między interfacea a type.

W tym przykładzie moim celem jest przypisanie prostego obiektu do szerszego Record<string, string>typu:

interface MyInterface {
  foobar: string;
}

type MyType = {
  foobar: string;
}

const exampleInterface: MyInterface = { foobar: 'hello world' };
const exampleType: MyType = { foobar: 'hello world' };

let record: Record<string, string> = {};

record = exampleType;      // Compiles
record = exampleInterface; // Index signature is missing

Spróbuj

Przypisanie jest możliwe przy deklarowaniu mojego obiektu za pomocą type, ale nie przy deklarowaniu podobnego za pomocą interface. Mówi, że brakuje podpisu indeksu, ale według mojego (ograniczonego) zrozumienia podpisów indeksu, żaden z nich nie ma MyTypei MyInterfacefaktycznie go nie ma.

Jaki jest powód, dla którego ostatnia linia nie kompiluje się, a poprzednia tak?

Odpowiedzi

2 ddprrt Nov 23 2020 at 21:51

Record<string, string>jest taki sam jak { [key: string]: string }. Podzbiór może zostać przypisany do tego typu sygnatury indeksu jest możliwy tylko wtedy, gdy wszystkie właściwości tego typu są znane i można je sprawdzić pod kątem tego podpisu indeksu. W Twoim przypadku wszystko z exampleTypemożna przypisać do Record<string, string>. Można to sprawdzić tylko dla typów literałów obiektowych, ponieważ typów literałów obiektowych nie można zmienić po ich zadeklarowaniu. W ten sposób znana jest sygnatura indeksu.

Źródło: https://github.com/microsoft/TypeScript/pull/7029

Natomiast interfejsy nie są ostateczne w momencie ich zadeklarowania. Zawsze istnieje możliwość dodania nowych członków do tego samego interfejsu ze względu na łączenie deklaracji.