Typescript,将类型从对象映射到元组

Typescript,将类型从对象映射到元组,typescript,typescript-generics,Typescript,Typescript Generics,考虑以下接口: 接口主题{ 颜色:{ 主要:{ 灯光:弦 基数:字符串 黑暗:弦 } 中学:{ 打火机:细绳 灯光:弦 基数:字符串 黑暗:弦 深色:细绳 } } } 我正在尝试编写一个允许元组的类型,第一个元素映射到颜色中的任何键,第二个元素映射到该颜色下的任何键(即:base) 即: ['primary','light']✅ 有效的 [“次要的”,“较暗的”]✅ 有效的 ['primary','darker']这里有两个选项,一个是泛型,需要指定它或一个并集: //通用方法 类型Typle

考虑以下接口:

接口主题{
颜色:{
主要:{
灯光:弦
基数:字符串
黑暗:弦
}
中学:{
打火机:细绳
灯光:弦
基数:字符串
黑暗:弦
深色:细绳
}
}
}
我正在尝试编写一个允许元组的类型,第一个元素映射到
颜色中的任何键,第二个元素映射到该颜色下的任何键(即:
base

即:

['primary','light']✅ 有效的
[“次要的”,“较暗的”]✅ 有效的

['primary','darker']这里有两个选项,一个是泛型,需要指定它或一个并集:

//通用方法
类型Typle=[K,主题键['color'][K]];
常量test1:Typle=['primary','light'];
常量test2:Typle=[“次要的”,“较暗的”];
常量test3:Typle=['主','暗'];//失败
//联合方式。
类型Typle2=K是否为主题['color']?[K,主题键['color'][K]]:从不;
常量test4:Typle2=['primary','light'];
常量test5:Typle2=[“次要的”,“较暗的”];
常量test6:Typle2=['主','暗'];//失败

否则,您需要一个创建函数来避免所需的泛型值

//一种助手函数方式。
常量craeteType=(v:Typle):Typle=>{
返回v;
}
const test7=cratetype(['primary','light']);
const test8=craettetype(['secondary','darker']);
const test9=craetype(['primary','darker']);//失败

事实上,你们非常接近。唯一缺少的是分发颜色密钥:

type ColorKey = keyof Theme['color'];
type ShadeKey<K extends ColorKey> = keyof Theme['color'][K];

type PickThemeColor<C extends ColorKey> = C extends ColorKey ? [C, ShadeKey<C>] : never;

const x1: PickThemeColor<'primary' | 'secondary'> = ['primary', 'light'] // OK
const x2: PickThemeColor<'primary' | 'secondary'> = ['secondary', 'darker'] // OK
const x3: PickThemeColor<'primary' | 'secondary'> = ['primary', 'darker'] // Error
type ColorKey=keyof Theme['color'];
键入ShadeKey=keyof Theme['color'][K];
键入PickThemeColor=C扩展颜色键?[C,ShadeKey]:永远不会;
常量x1:PickThemeColor=['primary','light']//确定
常量x2:PickThemeColor=['secondary','darker']//确定
常量x3:PickThemeColor=['primary','darker']//错误


ColorKey
ShadeKey
提取的地方只是为了简化
选择颜色
(这里没有新内容)。区别在于
C扩展了ColorKey
部分,因为它覆盖了颜色键的并集

因此
选择颜色将产生
[“主”、“亮”、“底”、“暗”]

选择颜色
将产生

[“主要”,ShadeKey]|[“次要”,ShadeKey]

谢谢!有一件事,我的智能感知是为第二个参数建议所有可能的值,而不是将它们限制在第一个参数的键上,有办法解决这个问题吗?啊,那么我认为我们需要删除主题['color']
=keyof,并始终将其设置为
:Typle
。我已经更新了答案。谢谢!这看起来很棒。我仍然看到与上面相同的地方,我对第二个元组值的intellisense总是建议所有可能的值(而不是基于第一个参数的有效值)-这可能吗?关于intellisense,我不确定,但是类型检查正如您所看到的那样工作
type ColorKey = keyof Theme['color'];
type ShadeKey<K extends ColorKey> = keyof Theme['color'][K];

type PickThemeColor<C extends ColorKey> = C extends ColorKey ? [C, ShadeKey<C>] : never;

const x1: PickThemeColor<'primary' | 'secondary'> = ['primary', 'light'] // OK
const x2: PickThemeColor<'primary' | 'secondary'> = ['secondary', 'darker'] // OK
const x3: PickThemeColor<'primary' | 'secondary'> = ['primary', 'darker'] // Error