为什么我收到错误"对象文字可能只指定已知属性"?

Rya*_*ugh 52 typescript

我刚刚从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 });
Run Code Online (Sandbox Code Playgroud)

代码看起来很好.怎么了?

(另类宇宙版:我认识到错字,我真的很想写那个.我该怎么做才能删除错误?)

Rya*_*ugh 118

从TypeScript 1.6开始,对象文字中的属性在它们被分配的类型中没有相应的属性被标记为错误.

通常,此错误表示您的代码或定义文件中存在错误(通常是拼写错误).在这种情况下正确的解决方法是修复错字.在这个问题中,该属性callbackOnLoactionHash是不正确的应该是callbackOnLocationHash(注意拼写错误的"位置").

此更改还需要在定义文件中进行一些更新,因此您应该为您正在使用的任何库获取最新版本的.d.ts.

例:

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

但我打算这样做

在某些情况下,您可能打算在对象中添加额外的属性.根据您正在做的事情,有几个适当的修复程序

仅检查某些属性的类型

有时你想确保存在一些东西和正确的类型,但是无论出于什么原因都打算有额外的属性.类型断言(<T>vv 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;
Run Code Online (Sandbox Code Playgroud)

这些属性可能更多

一些API接受一个对象并动态迭代其键,但具有需要属于某种类型的"特殊"键.向该类型添加字符串索引器将禁用额外的属性检查

之前

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

// Error
createModel({name: 'hello', length: 100});
Run Code Online (Sandbox Code Playgroud)

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

// OK
createModel({name: 'hello', length: 100});
Run Code Online (Sandbox Code Playgroud)

这是一只狗,一只猫或一匹马,还不确定

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' };
}
Run Code Online (Sandbox Code Playgroud)

这里有两个好的解决方案

指定一个封闭集 x

// Removes all errors
let x: Dog|Cat|Horse;
Run Code Online (Sandbox Code Playgroud)

类型断言每件事

// For each initialization
  x = { move: 'doggy paddle', woof: 'bark' } as Dog;
Run Code Online (Sandbox Code Playgroud)

这种类型有时是开放的,有时不是

使用交集类型的"数据模型"问题的干净解决方案:

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 });
Run Code Online (Sandbox Code Playgroud)

另请参见https://github.com/Microsoft/TypeScript/issues/3755

  • 我认为打字稿的主要优点是类型安全并减少我们创建的错误和潜在危险代码的数量 - 自动完成只是一个额外的好处。 (3认同)