typescript - 获取只读数组元素成员的 TypeScript 类型
问题描述
我有一个readonly Pokemon[]
名为PokemonData
. 每个元素都有一个name
成员。是否可以制作type
一个串联的口袋妖怪名称列表?
interface Pokemon {
readonly name: string;
// ...
}
const PokemonData: readonly Pokemon[] = [{
name: 'Pikachu',
// ...
}, {
name: 'Bulbasaur',
// ...
}] as const;
type PokemonName = // TODO: should be 'Pikachu' | 'Bulbasaur'
如果我有一个只有名称的数组,我可以轻松地做到这一点:
const pokemonNames = [ 'Pikachu', 'Bulbasaur' ] as const;
type ArrayType<T> = T extends readonly (infer U)[] ? U : never;
type PokemonName = ArrayType<typeof pokemonNames>;
我怀疑,如果这完全可行,我需要与ArrayType<T>
上面的对象属性等效的对象和/或接受 aPokemon
并返回其名称的函数。
// using a type approach (doesn't work)
type GetPokemonName<T extends Pokemon> = T['name'];
type GetPokemonNames<T> = T extends Pokemon[] ? GetPokemonName<T[/* something here */]> : never;
// using a function approach (may work, but I don't know how to convert it to a type)
function getPokemonName(pkmn: Pokemon) {
return pkmn.name;
}
我还认为可能ReadonlyArray<T>.map()
有用,但它只返回一个字符串类型。
const pokemonNames = PokemonData.map(p => p.name); // using 'as const' throws a compile-time error
type PokemonName = ArrayType<typeof pokemonNames>;
解决方案
Typescript 能够将数组中的名称视为字符串文字类型的唯一方法是删除: readonly Pokemon[]
类型注释;否则任何typeof
人都将查看Pokemon
类型的声明,而不是从数组的实际内容推断出的更具体的类型。
如果删除该注释,则名称可以映射到联合类型:
const PokemonData = [{
name: 'Pikachu'
}, {
name: 'Bulbasaur'
}] as const;
type PokemonName = (typeof PokemonData)[number]['name'];
将[number]
数组类型映射到其组件类型,然后映射到与属性['name']
关联的字符串文字类型的联合。name
这不是一个理想的解决方案,因为删除Pokemon[]
类型注释意味着 Typescript 不会检查其内容是否为有效Pokemon
对象。如果需要,可以编写一个辅助函数:
function pokemon<K extends string>(obj: Pokemon & { name: K }): Pokemon & { name: K } {
return obj;
}
const PokemonData = [
pokemon({
name: 'Pikachu',
}),
pokemon({
name: 'Bulbasaur',
}),
] as const;
推荐阅读
- python - Python:如何创建名称为变量的数据框?
- c# - 关于带参数的 Debug.Writeline() 的简单 C# 问题
- apache-kafka-streams - Kafka Streams transform() 状态存储
- google-cloud-messaging - 2019 年 1 月之后谷歌网络推送 GCM 响应的延迟
- html - Html/js单色字符
- vue.js - 如何在 vuex 中添加元素并且不开始计算值?
- r - R数据包 - 自动检测数据结构并包含在@format下
- javascript - JS/jQuery 库为所有不被接受的子元素添加样式
- python - 使用入口值调用函数返回框架
- node.js - 节点 js mysqlquery 尝试添加 .then