gpt4 book ai didi

typescript - TypeScript 中的递归索引签名

转载 作者:行者123 更新时间:2023-12-04 09:32:25 28 4
gpt4 key购买 nike

我正在尝试向嵌套对象添加索引签名类型,以便我可以通过计算值访问其某些属性。
例如,给定这个对象:

export const english = {
home: {
title: 'Title',
characters_list: 'Characters list',
moves: 'Moves',
header: 'Home',
search: 'Search',
},
character: {
detail: {
about: {
title: 'About',
info: 'Info',
full_name: 'Full name',
status: 'Status',
gender: 'Gender',
},
origin: {
title: 'Origin',
origin: 'Origin',
current_location: 'Current location',
},
},
},
}
我想像这样访问它的属性:
const key = 'moves';
english.home[key]
但我做对了。到目前为止,我已经能够输入第一层
export type Translation = {
[key: string]: typeof english[keyof typeof english]
}
我认为这需要某种递归方法,但我不知道如何实现它

最佳答案

好的,我想我知道我们需要做什么了。问题是对象允许键是类型 string 中的每个值。 ,但是一旦你定义了一个类型,你就会使用 string 的一个子集。 .因此,TypeScript 会抛出 - 理所当然地 - 一个错误,您不能只访问每个字符串,而只能访问作为有效键的字符串(例如 movestitle 等)
因此,在某个时间点,您必须确保要访问的 key 是有效的。
以下是可能性
a) 字符串文字 w const context
你分配的那一刻

const key = 'moves'
key不是类型 string ,但类型为 'moves' ,一个非常具体的值类型(或文字类型)和 string 的子类型.此访问应该有效
const key = 'moves'
english.home[key] // 👍
或者,定义它们 as const达到同样的效果
let key = 'moves' as const // also 'moves', not string
与通用选择功能相同的行为
function pick<T extends Object, K extends keyof T>(o: T, k: K) {
return o[k]
}
pick(english.home, 'moves')
pick(english, 'home')
pick(pick(english, 'home'), 'moves')
这与直接属性访问基本相同,但您可以让通用约束帮助您找到正确的类型。
b) 输入谓词以缩小范围
但是您不是在使用字符串文字,而是在使用计算键。这意味着您必须以某种方式从大字符串集到较小的实际键集。你可以用一个函数来检查这个键是否有效(你应该这样做),以及一个类型谓词来缩小控制流中的类型(你会看到那是什么)
所以想象一个这样的辅助函数:
function isKeyOf<O extends Object>(o: O, k: string | number | symbol): k is keyof O {
return typeof k === "string" && Object.keys(o).indexOf(k) >= 0
}
这个函数有很多事情要做。
  • 我们定义了一个称为 O 的泛型,它是一个对象
  • 的约束。
  • 我们允许使用 key k传入的可以是所有可能的对象键类型
  • 然后我们检查它是否是一个正确的字符串属性访问器,以及它是否在键列表中。如果是这样,我们可以有把握地说 k 的类型是 keyof O

  • 类型谓词适用于返回 bool 值的函数。如果此条件为真,则类型变得不同(即 keyof O )
    您可以使用它来创建 pickSafe功能,您可以在其中传递任何键
    function pickSafe<T extends Object>(o: T, k: string) {
    if (isKeyOf(o, k)) {
    return o[k]
    }
    throw new Error('Not accessible')
    }


    pickSafe(english.home, 'moves')
    pickSafe(english, 'home')
    pickSafe(pickSafe(english, 'home'), 'moves')
    问题是,虽然此访问有效,但您会丢失有关正在访问的对象的信息。那么您需要进行运行时类型检查。做
    const res = pickSafe(english, 'home')
    .. 并将鼠标悬停在 res ,你会看到哪些可能的类型可以从中产生
    这实际上是期望的行为,因为它会告诉您应用程序中可能不清楚的地方。
    如果您真的知道您的应用程序可以运行并且计算出的键是它们的样子,您可以随时进行类型转换以覆盖 TypeScript 的不确定性
    const keyey = myRandomString as keyof typeof english.home
    pick(english.home, keyey)
    这里是您的游乐场 fiddle around .
    我希望这有帮助!

    关于typescript - TypeScript 中的递归索引签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62777709/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com