Typographie attribuant une interface ou un type à un Record <string, string>

Nov 23 2020

Après avoir lu cette question ou cet article , je suis encore un peu confus sur les différences subtiles entre un interfaceet un type.

Dans cet exemple, mon objectif est d'assigner un objet simple à un Record<string, string>type plus large :

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

Essayez-le

L'affectation est possible lors de la déclaration de mon objet avec a type, mais pas lors de la déclaration d'un objet similaire avec un interface. Il dit que la signature d'index est manquante, mais à ma compréhension (limitée) des signatures d'index, aucune MyTypeet n'en MyInterfacepossède une.

Quelle est la raison pour laquelle la dernière ligne ne compile pas alors que la précédente le fait?

Réponses

2 ddprrt Nov 23 2020 at 21:51

Record<string, string>est le même que { [key: string]: string }. L'affectation d'un sous-ensemble à ce type de signature d'index n'est possible que si toutes les propriétés de ce type sont connues et peuvent être vérifiées par rapport à cette signature d'index. Dans votre cas, tout exampleTypeest attribuable à Record<string, string>. Cela ne peut être vérifié que pour les types littéraux d'objet, car les types littéraux d'objet ne peuvent pas être modifiés une fois que vous les avez déclarés. Ainsi, la signature d'index est connue.

La source: https://github.com/microsoft/TypeScript/pull/7029

En revanche, les interfaces ne sont pas définitives au moment où vous les déclarez. Il y a toujours la possibilité d'ajouter de nouveaux membres à la même interface en raison de la fusion des déclarations.