typescript 如何Assert一个值是一个有效的键,而不知道对象的键在编译时?

lpwwtiir  于 2023-01-21  发布在  TypeScript
关注(0)|答案(2)|浏览(161)

在TypeScript中,有没有什么方法可以在不知道Record的键是什么的情况下声明变量是keyofRecord
假设一个API响应返回一个JSON的有效载荷。我想为有效载荷的键定义一个类型,这样我就可以索引有效载荷,并且知道值不会是未定义的。这是可能的吗?或者我必须在每次索引有效载荷对象时简单地检查未定义吗?
示例:

const payload: Record<string, ValidValue> = await myApiCall()

const prop1 = 'a'
const prop2 = 'b'

if (isValidKey(prop1, payload)) {
  const value1 = payload[prop1] // the type of `value1` should evaluate to `ValidValue`
}

const value2 = payload[prop2] // the type of `value2` should evaluate to `ValidValue | undefined`
z3yyvxxp

z3yyvxxp1#

我也使用了一个类型保护函数,但没有返回key is keyof MyMap,而是为Record<string, ValidValue | undefined>的有效负载对象指定了一个类型,然后类型保护函数返回payload is Record<K, ValidValue>,其中K是键参数的类型。
你可以在TSPlayground玩它。

// Type alias for convenience
type Payload = Record<string, ValidValue | undefined>;

const payload: Payload = await myApiCall()

function isValidKey<K extends string>(key: K, payload: Payload): payload is Record<K, ValidValue> {
  return key in payload;
}

const prop1 = 'a'
const prop2 = 'b'

if (isValidKey(prop1, payload)) {
  const value1 = payload[prop1] // the type of `value1` should evaluate to `ValidValue` ✅
}

const value2 = payload[prop2] // the type of `value2` should evaluate to `ValidValue | undefined` ✅
nhhxz33t

nhhxz33t2#

我想我找到了解决办法。这在TS操场上似乎和预期的一样有效。

const myMap = [1,2,3].reduce((p, n) => ({ ...p, [Math.random()]: n }), {})

type MyMap = typeof myMap

console.log('myMap', myMap)

function isKnownKey(key: string, thing: MyMap): key is keyof MyMap {
    return Object.keys(thing).includes(key)
}

const knownTypes = ['a', 'b']
const prop1 = Object.keys(myMap)[0]
const prop2 = 'b'

if (isKnownKey(prop1, myMap)) {
    const value1 = myMap[prop1]
    console.log('value1', value1)
}

const value2 = myMap[prop2]
/*
TS Error:
Element implicitly has an 'any' type because expression of type '"b"' can't be used to index type '{}'.
  Property 'b' does not exist on type '{}'.(7053)
*/

但是,有一件事我不明白:value1的计算结果是never类型,但是没有TS错误,这是怎么回事?

相关问题