できない.dev

TypeScript でオブジェクトリテラルに余分なプロパティを指定できない

「Object literal may only specify known properties」はオブジェクトリテラルに対する厳密チェック。
一度変数に代入する、型を拡張する、または index signature を加えると解消する。

#excess-property#type#object-literal#narrowing

公開:

要約

「Object literal may only specify known properties, and 'foo' does not exist in type 'Bar'」は TypeScript のオブジェクトリテラルに対する excess property check によるエラー。
リテラルを直接渡すと型に無いプロパティが拒否されるが、変数経由で渡すか型を広げれば回避できる。

よくある原因

  1. オブジェクトリテラル直渡し: TypeScript はリテラル経由の場合に限り、未定義プロパティを誤入力とみなして拒否する。
  2. 受け取り型が完全一致を要求: 関数引数や変数の型が optional プロパティを許しておらず、追加プロパティが想定されていない。
  3. タイポ: colourcolor のような単純な綴り間違いで、TypeScript が親切にエラーを出している。
  4. 型の更新漏れ: 実装側で増やしたプロパティを型定義に反映し忘れている。

解決策

1. 一度変数に入れる

excess property check は オブジェクトリテラルの直渡しのみ に効く。
変数に入れてから渡すと構造的部分型のチェックに切り替わり、追加プロパティが許される。

type Props = { name: string };
declare function render(p: Props): void;
 
// NG: excess property check
render({ name: "a", extra: 1 });
 
// OK: 変数経由
const obj = { name: "a", extra: 1 };
render(obj);

ただし「タイポをすり抜ける」副作用もあるため安易に使わない(公式ドキュメント)。

2. 型に optional / index signature を追加する

将来的に拡張可能にしたい場合は型側を広げる。

type Props = {
  name: string;
  extra?: number;        // 任意プロパティを明示
};
 
type Loose = {
  name: string;
  [key: string]: unknown; // 任意キーを許可
};

[key: string]: T の index signature を入れると任意のキーを受け付けるようになる。

3. typo を直す

colourcolor にするだけで解消するケースが意外と多い。
エラーメッセージ末尾の Did you mean 'color'? を信用する。

4. 最後の手段としての as

どうしても通す必要があるなら as で抑えるが、型安全性が崩れるので避ける。

render({ name: "a", extra: 1 } as Props);

ライブラリ側の型定義が古いだけなら、declare module で型を上書きするほうが安全。

この記事は役立ちましたか?