我正在尝试从另一个对象扩展某些属性:
interface IAlice {
foo: string;
bar: string;
};
interface IBob extends IAlice {
aFunction(): number;
anotherValue: number;
};
let alice: IAlice = {
foo: 'hi',
bar: 'bye'
};
let bob: IBob = Object.assign({}, alice); // Typescript error no aFunction & anotherValue
bob.anotherValue = 2;
bob.aFunction = (): number => {
return 3;
}
如您所见,打字稿返回错误。
我知道一个可行的解决方法是使bob值可选,但这并不能解决问题。或者在Object.assign内部分配值也不起作用,因为有一个函数。
无论如何,有没有让打字稿识别出将要定义的值?
答案 0 :(得分:3)
如果bob
的类型为IBob
,则必须始终定义IBob
的所有字段。最简单的解决方案是创建完全形成为IBob
实例的对象:
let bob: IBob = Object.assign({
anotherValue: 2,
aFunction : (): number => {
return 3;
}
}, alice);
如果要部分初始化对象并缺少某些字段,可以使用Partial
:
let bob: Partial<IBob> = Object.assign({}, alice);
bob.anotherValue = 2;
bob.aFunction = (): number => {
return 3;
}
这将使所有字段都是可选的,这在所有情况下可能都不适用,但是最好记住Partial
作为选项。
如果您真的想打字,甚至可以将IBob
的字段设为可选,同时将IAlice
的字段保留为必填
let bob: Partial<Pick<IBob, Exclude<keyof IBob, keyof IAlice>>> & IAlice = Object.assign({}, alice);
bob.anotherValue = 2;
bob.aFunction = (): number => {
return 3;
}
具体说明什么是可选的而不是什么是重要的原因在于,除非您明确检查null,否则在strictNullChecks
下您将无法访问可选字段。
蛮力不安全选项是仅使用类型断言来使分配工作。为了完整起见,我将其包括在内,但我会避免断言在可能的情况下是不正确的(您基本上是向编译器说谎,Object.assign
的结果具有IBob
的所有字段,而编译器会错过了可能由那些缺少的字段引起的错误)
let bob: IBob = Object.assign({}, alice) as IBob;
// Or (but only if you are not in a tsx file)
let bob: IBob = <IBob>Object.assign({}, alice);
答案 1 :(得分:0)
您可以这样做:
convertDotNotationToArray(objectWithDotNotation) {
Object.entries(objectWithDotNotation).forEach(([key, val]) => {
// Is the key of dot notation
if (key.includes('.')) {
const [name, index] = key.split('.');
// If you have not created an array version, create one
if (!objectWithDotNotation[name]) {
objectWithDotNotation[name] = new Array();
}
// Save the value in the newly created array at the specific index
objectWithDotNotation[name][index] = val;
// Delete the current dot notation key val
delete objectWithDotNotation[key];
}
});
}
现在可以将let bob: IBob | IAlice = Object.assign({}, alice);
和IBob
这两种类型的对象都分配给IAlice
。