我只想循环一个类的某些键。我不希望使用索引签名[key:string]:any
,因为不建议这样做。
这是我的主意
interface I {
a: string,
b: number
}
type NullKeysOf<T> = {
[P in keyof T]: null
}
type PartialNullKeysOf<T> = Partial<NullKeysOf<T>>;
const obj:PartialNullKeysOf<I> = {
a:null
}
class A<M extends I> implements I{
a:string;
b:number;
obj:PartialNullKeysOf<M>
constructor(a:string, b:number, obj:PartialNullKeysOf<M>){
this.a = a;
this.b = b;
this.obj = obj;
}
public loop(){
for(const k in this.obj){
console.log(this[k]);
}
}
}
const a = new A<I>('',3,obj);
a.loop();
这是打字机游乐场link
我得到了错误
Type 'Extract<keyof M, string>' cannot be used to index type 'this'.
为什么循环中k
的类型是Extract<keyof M, string>
?
不应该是typeof I
吗?
答案 0 :(得分:0)
为什么循环中k的类型是Extract
您将 obj
成员输入为 PartialNullKeysOf<M>
。 for...in
循环枚举对象的 string
键,因此 k
的类型被推断为“从 M 类型的给定值中获取所有字符串键”:
keyof M
为您提供 M
(string | number | symbol
union) 中的键类型Extract
只留下 string
类型的键(第二个泛型类型参数)M
,而不是 I
(尽管 I
是 constrained)以上所有结果都导致 k
被推断为 Extract<keyof M, string>
不应该是我的类型吗?
不,不应该,参见第 3 点。泛型类型参数中的 extends
与继承无关,而是类型的兼容性。 M
仅检查与 I
兼容。
类型 'Extract
正如评论中已经指出的,I
和 M
之间没有相关性:你知道它们是相同的,并不意味着编译器可以< em>安全地假设。幸运的是,在您的情况下可以避免类型断言:
public loop(this: A<M> & M){ // <-- "this" now knows about members of M
for(const k in this.obj){
console.log(this[k]); //OK
}
}
this
parameter 确保您既保留 this
(A<M>
) 的原始类型,并明确告诉编译器 this
具有类型的成员M
。