【发布时间】:2021-07-08 22:29:02
【问题描述】:
这种东西我编译不出来:
type F<A> = (a:A)=>A;
class CLAZZ<S extends { [k: string]: any }, K extends keyof S = keyof S>{
constructor(a:S){
this._o=a;
}
_o:S;
set(k:K, f:F<S[K]>){
f(this._o[k]);
}
}
type O = {
pippo: number,
pluto: string | null,
paperino: {[k:string]:boolean}
}
let o = new CLAZZ<O>({"paperino":{}, pluto:null, pippo:1});
o.set("paperino", (paperino)=>({...paperino, "ciccio":true}))
最后一行给出这个错误:
传播类型只能从对象类型创建。
这是因为 paperino 参数被推断为
(参数)paperino:字符串|号码 | { [k:字符串]:布尔值; } |空
不只是
{ [k: 字符串]: 布尔值; }
正如我所期待的......
也强制参数类型给我一个错误
o.set("paperino", (paperino: {[k:string]:boolean})=>({...paperino,"ciccio":true}))
类型参数 '(paperino: { [k: string]: boolean; }) => { ciccio: true; }' 不可分配给类型参数 'F'。种类 参数“paperino”和“a”不兼容。 键入'字符串 |号码 | { [k:字符串]:布尔值; } | null' 不能分配给类型 '{ [k: string]: boolean; }'。 类型 'null' 不能分配给类型 '{ [k: string]: boolean; }'。
除了...“任何”之外的任何解决方案?
【问题讨论】:
-
因为 TS 在您创建对象时计算类型,而不是在您调用
set时计算类型,如果您希望在调用函数时缩小类型,您也可以将其设为泛型,例如set<K1 extends K>(k:K1, f:F<S[K1]>)应该可以。 (CLAZZ<O>看起来有点拼写错误:D)
标签: typescript typescript-generics