interface Opts {
onFrame: () => void;
onAudioSample: null;
emulateSound: boolean;
sampleRate: number;
}
class NES {
constructor(opts: Opts) {
this.opts = {
onFrame() { },
onAudioSample: null,
emulateSound: true,
sampleRate: 44100,
}
if (typeof opts !== "undefined") {
let key: keyof Opts
for (key in this.opts) {
if (typeof opts[key] !== "undefined") {
// got err here
this.opts[key] = opts[key];
}
}
}
}
opts: Opts
}
您可以在TS游乐场检查错误:here
打字稿:v3.8.3
err: Type 'number'
无法分配给类型never
。
我不明白为什么它是never
类型。
答案 0 :(得分:2)
您收到该错误,因为TypeScript无法推断this.opts[key]
和opts[key]
是同一类型。如果您要掩盖=
的每半部分:
opts[key]
可以是Function
,null
,boolean
或number
this.opts[key]
需要接收Function
,null
,boolean
或number
取决于key
的值,我们不知道Function
,null
,boolean
和number
的唯一共同的超类型是never
,
这就是TypeScript想要的this.opts[key]
有趣的是,如果要将其提取到匿名泛型函数中,它将起作用:在单个赋值中,Typescript 可以推断并使用类型Opts[K]
。 jcalz在this similar question中提出了类似的解决方案。
if (typeof opts[key] !== "undefined") {
// this.opts[key] = opts[key];
(<K extends keyof Opts>(k: K) => { this.opts[k] = opts[k]; })(key);
}
也就是说,我将像Mukesh Soni's answer中那样使用散布运算符,以this.opts
结束对...opts
的赋值,或者使用Object.assign
。传递的opts
包含额外的键会有一点风险,但是Typescript应该在编译时确保否则。 (因此,如果您期望opts
是可选的并且可能不完整,则应将其定义为opts?: Partial<Opts>
。)
class NES {
constructor(opts?: Partial<Opts>) {
this.opts = Object.assign({
onFrame() { },
onAudioSample: null,
emulateSound: true,
sampleRate: 44100,
}, opts);
}
opts: Opts
}
另请参见: Object spread vs. Object.assign,它指出解决方案非常相似,并且都适用于默认选项值。
答案 1 :(得分:1)
我不知道您为什么会收到该错误。合并这两个选项的另一种方法可能是使用扩展运算符。
this.opts = {
onFrame() { },
onAudioSample: null,
emulateSound: true,
sampleRate: 44100,
...opts
};
答案 2 :(得分:0)
如果在属性访问之后放置as any
,TypeScript将检查key
是有效的密钥
if (typeof opts[key] !== "undefined") {
(this.opts[key] as any) = opts[key];
}