微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

打字稿中的从属类型-通过属性名称类型确定类型

如何解决打字稿中的从属类型-通过属性名称类型确定类型

我试图使类型取决于所传递参数的类型。 一个人为的例子是:

type NS = "num" | "str"
type Data<T extends NS> = T extends "num" ? number : string
type Func<T extends NS> = (x: Data<T>) => Data<T>
type Funcs = {[T in NS]: Func<T>}
type Obj = {[T in NS]: Data<T>}
const funcs: Funcs = {
  num: (x) => x * 2,str: (x) => x + x
}

function useFunc<T extends NS>(ns: T,obj: Obj): Data<T> {
  const f = funcs[ns]
  const x = obj[ns]
  return f(x)
}

问题是f(x)的类型为number | string而不是Data<T>,这似乎是由f的类型为Funcs[T]而不是Func<T>引起的。 x的类型也为Obj[T],而不是Data<T>

因此即使Funcs[T]Func<T>Obj[T]Data<T>Funcs是相同的,并且Objfunction useFunc<T extends NS>(ns: T,obj: Obj): Data<T> { const f = funcs[ns] as Func<T> const x = obj[ns] as unkNown as Data<T> // note the double-cast as Obj[T] and Data<T> "do not sufficiently overlap" return f(x) } 是相同的,打字稿也不能推断出它们相同。 function useFunc<T extends NS>(ns: T,obj: Obj): Data<T> function useFunc(ns: NS,obj: Obj): Data<NS> { if (ns === "num") { const f = funcs[ns] const x = obj[ns] return f(x) } const f = funcs[ns] const x = obj[ns] return f(x) } 已定义...

我可以通过类型转换使它正常工作,但是它违反了使用类型的目的:

IIF([Data From System$].[Data Dim#] IS NULL,[Data From System$].[Data Dim#]
   ) AS [Value]

有没有办法使它在打字稿中起作用?

编辑:

我知道可以通过这种方式使其工作,并且可以在调用站点上使用,但是从代码重用的角度来看毫无意义-在不同类型上组合相同的逻辑是这样做的实际动力,并且这样就可以简单地重复。

IIF()

有没有办法避免这种重复而又不会失去类型安全性?

解决方法

主要问题是,当TS推断f签名为useFunc时,您试图在f内部调用(x: never) => string | numer函数。此签名与funcs对象中的每个签名都不兼容。

另外,正如我所说,应将签名useFunc<T extends NS>(ns: T,obj: Obj): Data<T>简化为useFunc<T extends NS>(ns: T,obj: Data<T>): Data<T>,甚至最好将其更正。这是因为TS应该知道您将传递给f的数据的类型,以便能够进行类型检查。另外,另一个需要进行上述修改的原因是useFunc函数调用仅在ns等于"num""str"的情况下可用,但不能同时使用。由于上述原因,obj参数类型将为Data<"num">Data<"str">。因此,将其键入为Obj是错误的。

可能的更改最少的解决方案是:

function useFunc<T extends NS>(ns: T,arg: Data<T>): Data<T> {
  const f = funcs[ns]
  return (f as Func<T>)(arg)
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。