TypeScript测试记录的值示例

aurhwmvo  于 2022-12-14  发布在  TypeScript
关注(0)|答案(2)|浏览(120)

有没有办法在TypeScript中测试一个值是否是Record类型的示例?我需要一个能够正确区分变量何时可能也是数组的case。

function(a: Record<string,string>|string[]) {
  if( a instanceof Record ) {
     do_stuff( a.key )
  }
}

我知道这在JavaScript中是有问题的,因为我的两个类型都是对象,因此在这两种情况下都是typeof(a) == "object"

  • 我知道Record类型在运行时实际上并不存在,但是该示例应该阐明我尝试做的事情。同样重要的是,测试正确地通知TypeScript缩小的类型,以便a.key不会产生错误。*
ruarlubt

ruarlubt1#

根据文档,Record<K, V>是一个键为K,值为V的对象。由于原型链的存在,“真正的”Record<string, string>并不存在,这会导致对象继承例如.toString()方法。但是考虑完整的继承属性集会很麻烦(related discussion on the TS GitHub),因此最清楚的做法是将Record类型与an object's own properties一起使用:

// Allowed:
const foo: Record<string, string> = { bar: "bar" }

// Even though functions aren't a subtype of string:
type inheritedToString = typeof foo.toString
//   ~~~~~~~~~~~~~~~~~
//   inheritedToString = () => string

这意味着,通过将一种或多种迭代对象中属性的方法与TypeScript的类型 predicate 相结合,您很可能已经足够了:

function isStringRecord(obj: unknown): obj is Record<string, string> {
  if (typeof obj !== "object")
    return false

  if (Array.isArray(obj))
    return false

  if (Object.getOwnPropertySymbols(obj).length > 0)
    return false
  
  return Object.getOwnPropertyNames(obj)
    .every(prop => typeof obj[prop] === "string")
}

现在您将拥有:

const foo = { bar: "bar" } as unknown

if (isStringRecord(foo)) {
  foo // foo: Record<string, string>
}
hjqgdpho

hjqgdpho2#

您可以使用型别保护,根据执行阶段值来缩小的型别范围。您可以定义型别保护函式来检查的值,如果是预期的型别,则传回true,否则传回false。例如,您可以定义如下的型别保护:

function isRecord(a: Record<string, string> | string[]): a is Record<string, string> {
  // Check if a is an object and has a property called "key"
  return typeof a === 'object' && 'key' in a;
}

然后,您可以在if陈述式中使用这个型别保护,根据执行阶段值缩小的型别范围:

function doStuff(a: Record<string, string> | string[]) {
  if (isRecord(a)) {
    // At this point, TypeScript knows that a is of type Record<string, string>,
    // so you can safely access its properties without getting a type error.
    doSomething(a.key);
  } else {
    // a is not a Record, so it must be an array of strings
    doSomethingElse(a);
  }
}

此方法可让您正确区分这两种型别,并存取它们的属性,而不会发生型别错误。

相关问题