如何确保字符串键控对象在打字稿中是通用的[复制]

问题描述 投票:1回答:1

拥有一个带有字符串索引对象的泛型函数

function wantsStringIndexedObject<
    Obj extends { [k: string]: any }, 
    K extends keyof Obj
  >(obj: Obj, key: K) {

  const _ktype = typeof key
  // const ktype: "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"

  const val = obj[key]

  wantsStringAndAny(key, val)
  // Argument of type 'K' is not assignable to parameter of type 'string'.
  // Type 'keyof Obj' is not assignable to type 'string'.
  //    Type 'string | number | symbol' is not assignable to type 'string'.
  //    Type 'number' is not assignable to type 'string'.
  // (parameter) key: K extends keyof Obj
} 

// no error here
wantsStringIndexedObject({
  1: 10,
  [Symbol()]:1
}, 1) 

function wantsStringAndAny(str: string, v:any) {} 

TS playground

我知道在调用key之前我可以在wantsStringAndAny上使用类型防护,但我希望: 1:key应该在wantsStringIndexedObject内输入字符串 2:不应该允许用这种物体调用wantsStringIndexedObject

我想问题来自通用定义qazxsw poi 实际上,具有任何索引类型的对象扩展了具有0个属性的qazxsw poi。

那么,有没有办法定义一个确保字符串索引对象约束的泛型?

typescript typescript-generics
1个回答
2
投票

您可以通过使用Obj extends { [k: string]: any }条件类型来过滤{ [k: string]: any }的键来确保键是字符串类型:

Extract

通常,约束是类型必须实现的最小契约,没有什么能阻止实际类型在其键中包含符号。字符串索引实际上也允许使用字符串和数字进行索引,因此在您的假设下也允许使用数字。

如果您还想禁止Obj中的任何数字或符号键,您可以执行以下操作:

function wantsStringAndAny(str: string, v:any) {

} 

function wantsStringIndexedObject<
    Obj extends object, 
    K extends Extract<keyof Obj, string>
  >(obj: Obj, key: K) {

  const _ktype = typeof key
  const val = obj[key]

  wantsStringAndAny(key, val)
} 

// err
wantsStringIndexedObject({
  1: 10,
  [Symbol()]:1
}, 1)

//ok
wantsStringIndexedObject({
  "1": "",
}, "2")

这需要任何Objfunction wantsStringIndexedObject< Obj extends object, K extends Extract<keyof Obj, string> >(obj: Obj & Record<Extract<keyof Obj, number | symbol>, never>, key: K) { const _ktype = typeof key const val = obj[key] wantsStringAndAny(key, val) } //ok wantsStringIndexedObject({ "1": "", }, "1") wantsStringIndexedObject({ "1": "", 2: 0 // errr }, "1") 键,基本上说它们应该是number类型(可能但不太可能),你会在任何这样的键上得到一个错误。

© www.soinside.com 2019 - 2024. All rights reserved.