【问题标题】:Typescript Generics : what is wrong here?打字稿泛型:这里有什么问题?
【发布时间】: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}))

playground

最后一行给出这个错误:

传播类型只能从对象类型创建。

这是因为 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&lt;K1 extends K&gt;(k:K1, f:F&lt;S[K1]&gt;) 应该可以。 (CLAZZ&lt;O&gt; 看起来有点拼写错误:D)

标签: typescript typescript-generics


【解决方案1】:

只需将通用键移至set 方法:playground

【讨论】:

    猜你喜欢
    • 2018-05-06
    • 1970-01-01
    • 2021-04-07
    • 2015-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-26
    相关资源
    最近更新 更多