book icon indicating copy to clipboard operation
book copied to clipboard

interfaceとtypeの違いにimplicit index signature(暗黙的なインデックスシグネチャ)についての解説を追加してほしいです。

Open suin opened this issue 9 months ago • 0 comments

何をどうしたいか?

interfaceとtypeはindex signatureが明示的か暗黙的かの違いがあります。

interfaceとtypeの違いについて触れているページがありますが、現在これについて触れていません。なので、その解説を追加してほしいです。

この違いは次のコードで確認できます。このコードのPlaygroundはこちら

interface FooInterface {
  foo: string;
}

interface FooInterfaceWithIndexSignature {
  foo: string;
  [K: string]: string; // Explicit index signature
}

// Type alias has implicit index signature
type FooType = {
  foo: string;
};

declare const fooInterface: FooInterface;
declare const fooInterfaceWithIndexSignature: FooInterfaceWithIndexSignature;
declare const fooType: FooType;

const test1: { [K: string]: string } = fooInterface; // Error, since interfaces have no implicit index signature
const test2: { [K: string]: string } = fooInterfaceWithIndexSignature; // OK, since the type has explicit index signature
const test3: { [K: string]: string } = fooType; // OK, since type alias has implicit index signature

// Type-level is also same mannar
type UseIndexSignature<T extends { [K: string]: string }> = T;
type Test1 = UseIndexSignature<FooInterface>; // Error
type Test2 = UseIndexSignature<FooInterfaceWithIndexSignature>; // OK
type Test3 = UseIndexSignature<FooType>; // OK

// Work-arounds: value level
{
  const test1: { [K: string]: string } = { ...fooInterface }; // Destructuring has effect that unlink the interface type.
}

// Work-arounds: type level
{
  type Test1 = UseIndexSignature<Pick<FooInterface, keyof FooInterface>>;
}

上のコードにも示しましたが、interfaceをどうしてもindex signatureに代入したい場合は、値レベルであれば...を用いる。型レベルであれば、Pickを用いるなどの方法があります。interfaceが自分のプロジェクトのもので変更可能であるならば、typeに書き換えるのも対応策としてありです。

そうしたい理由は何か?

この違いがわからないと、「なぜか代入できない!」とハマってしまうから。

着手可能になったら自分でプルリクエストを作成したいか?

他の人でも可

※ 着手可になってから、1ヶ月以上経過している場合は他の人が着手する可能性があります。

suin avatar May 21 '24 01:05 suin