javascript - 打字稿:如何创建具有 2 项的元组,其中第 2 项使用第 1 项的值作为键?
问题描述
我想创建一个数组元组,其值 ['account', 'accountOne'] 使用现有类型,但第二个元组值应包含基于第一个选择的值。
下面的一些示例代码:
interface RootState {
account: Account;
movies: Movies;
config: Config;
}
interface Account {
accountOne: 'something',
accountTwo: '1'
}
interface Movies {
moviesOne: 'something',
moviesTwo: 'something'
}
interface Config {
configOne: 'something',
configTwo: '123'
}
export type ModuleProp = keyof RootState;
// This is some pseudo code, to show the idea, but I could not make it work
// It gives error: Tuple type arguments circularly reference themselves
export type ModulesTuple = [ModuleProp, keyof RootState[ModulesTuple[0]]
// It would be used as
function fetchSomething({page: number, vuexModuleProp: ModulesTuple}){
const [module, moduleProp] = vuexModuleProp
// rest of the code
}
fetchSomething({
page: 1,
vuexModuleProp: ['movies', 'accountOne'] // ERROR
})
fetchSomething({
page: 1,
vuexModuleProp: ['movies', 'moviesOne'] // GOOD TO GO
})
当前代码给出以下错误:元组类型参数循环引用自身
这个想法是,如果你选择'account'作为第一个元组,第二个选择应该是'accountOne'或'accountTwo',它们是RootState接口中其他接口(Movies,Account,Config)的嵌套键。
不确定 Typescript 是否可行,但非常感谢任何帮助!
解决方案
使用泛型。
interface RootState {
account: Account;
movies: Movies;
config: Config;
}
interface Account {
accountOne: 'something',
accountTwo: '1'
}
interface Movies {
moviesOne: 'something',
moviesTwo: 'something'
}
interface Config {
configOne: 'something',
configTwo: '123'
}
// All available modules
type ModuleKeys = keyof RootState;
// Pick a module interface based on type of `T`
type ModuleProps<T extends ModuleKeys> = T extends 'account'
? Account
: T extends 'movies'
? Movies
: T extends 'config'
? Config
: never;
// Creates a tuple where the second type is based on the first type, where the first type is automatically inferred from `T`.
type ModuleTuple<T extends ModuleKeys> = [T, keyof ModuleProps<T>];
// Guard the `T` type to be one of `ModuleKeys`, where it is passed to `ModuleTuple<T>`, where it creates the conditional tuple.
function fetchSomething<T extends ModuleKeys>({ page, vuexModuleProp }: { page: number, vuexModuleProp: ModuleTuple<T> }): any {
const [moduleKey, moduleProps] = vuexModuleProp;
console.log(page, moduleKey, moduleProps);
}
fetchSomething({
page: 1,
vuexModuleProp: ['movies', 'accountOne'] // ERROR
});
fetchSomething({
page: 1,
vuexModuleProp: ['movies', 'moviesOne'] // GOOD TO GO
});
检查操场。
推荐阅读
- r - 如何使用布局在r中的一页中排列复杂的图
- java - 使用 JSoup 解析特定元素
- java - 从命令行覆盖 Maven 插件中的属性
- python - 使用scrapy抓取时出现下一页问题
- javascript - 如果 CSS 呈现阻塞,我们如何拥有无样式内容的 Flash?
- angularjs - 错误:无法使用 webpack-4 解析“angular-ui-bootstrap”
- c - 使用 lodsb 使用内联 c 将字节移动到另一个地址
- javascript - 在控制器中更改 ng-model 值不会显示在 html 输入中
- python-3.x - 通过win32com在word文件中查找句子的范围
- python - 使用 sqlalchemy 连接两个表时出错