1. ホーム
  2. typescript

[解決済み] Object literal may only specify known properties" というエラーが発生するのはなぜですか?

2022-03-11 08:52:55

質問

TypeScript 1.5から最新版にアップグレードしたところ、コードにエラーが発生するようになりました。

interface Options {
   /* ... others ... */
   callbackOnLocationHash?: boolean;
}

function f(opts: Options) { /* ... */ }

//  Error: Object literal may only specify known properties,
//     and 'callbackOnLoactionHash'does not exist in type 'Options'.
f( { callbackOnLoactionHash: false });

コードは私には問題なく見えます。何が問題なのでしょうか?

(別世界バージョン。誤字に気づきました、本当にそのつもりで書きました。このエラーを取り除くにはどうしたらよいでしょうか?)

解決方法は?

TypeScript 1.6では、オブジェクトリテラルに含まれるプロパティのうち、代入先の型に対応するプロパティがないものはエラーとなる。

通常、このエラーは、コードや定義ファイルにバグ(通常はタイプミス)があることを意味します。この場合、正しい修正は、タイポを修正することです。質問では、プロパティ callbackOnLoactionHash は不正確であり、本来は callbackOnLocationHash ("Location"のスペルミスに注意).

この変更により、定義ファイルの更新も必要になりましたので、使用しているライブラリの最新版の .d.ts を取得する必要があります。

interface TextOptions {
    alignment?: string;
    color?: string;
    padding?: number;
}
function drawText(opts: TextOptions) { ... }
drawText({ align: 'center' }); // Error, no property 'align' in 'TextOptions'

しかし、私はそれを行うことを意味します

オブジェクトに余分なプロパティを持たせることを意図している場合がいくつかあります。何をしようとしているかに応じて、いくつかの適切な修正方法があります。

一部のプロパティのみタイプチェックする

時には、いくつかのものが存在し、正しい型であることを確認したいが、何らかの理由で余分なプロパティを持つことを意図している場合があります。このような場合には、型アサーション ( <T>v または v as T ) は、余分なプロパティをチェックしないので、タイプアノテーションの代わりに使用することができます。

interface Options {
    x?: string;
    y?: number;
}

// Error, no property 'z' in 'Options'
let q1: Options = { x: 'foo', y: 32, z: 100 };
// OK
let q2 = { x: 'foo', y: 32, z: 100 } as Options;
// Still an error (good):
let q3 = { x: 100, y: 32, z: 100 } as Options;

これらのプロパティと多分もっと

APIによっては、オブジェクトを受け取り、そのキーに対して動的に反復処理を行いますが、ある特定の型である必要がある「特別な」キーが存在します。その型に文字列インデクサを追加すると、余分なプロパティチェックが不要になります。

interface Model {
  name: string;
}
function createModel(x: Model) { ... }

// Error
createModel({name: 'hello', length: 100});

その後

interface Model {
  name: string;
  [others: string]: any;
}
function createModel(x: Model) { ... }

// OK
createModel({name: 'hello', length: 100});

これは、犬か猫か馬か、まだわからない。

interface Animal { move; }
interface Dog extends Animal { woof; }
interface Cat extends Animal { meow; }
interface Horse extends Animal { neigh; }

let x: Animal;
if(...) {
  x = { move: 'doggy paddle', woof: 'bark' };
} else if(...) {
  x = { move: 'catwalk', meow: 'mrar' };
} else {
  x = { move: 'gallop', neigh: 'wilbur' };
}

ここで、2つの良い解決策が思い浮かびます。

に閉じた集合を指定する。 x

// Removes all errors
let x: Dog|Cat|Horse;

または 各項目を入力します。

// For each initialization
  x = { move: 'doggy paddle', woof: 'bark' } as Dog;

このタイプは、開くときと開かないときがあります

交差型を使って、"データモデル"問題をきれいに解決します。

interface DataModelOptions {
  name?: string;
  id?: number;
}
interface UserProperties {
  [key: string]: any;
}
function createDataModel(model: DataModelOptions & UserProperties) {
 /* ... */
}
// findDataModel can only look up by name or id
function findDataModel(model: DataModelOptions) {
 /* ... */
}
// OK
createDataModel({name: 'my model', favoriteAnimal: 'cat' });
// Error, 'ID' is not correct (should be 'id')
findDataModel({ ID: 32 });

参照 https://github.com/Microsoft/TypeScript/issues/3755