作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我无法确定是否可以对类型中的泛型参数使用隐含值,就像在函数中一样。
假设我有以下接口(interface)定义我的一些数据库表的结构:
interface Tables {
'table-users': { userId: string, username: string },
'table-posts': { postId: string, userId: string, title: string },
}
我可以编写一个过于简化的函数,允许我使用以下方式写入这些表:
const write = <T extends keyof Tables>(table: T, item: Tables[T]): boolean => {
// ... do something
return true;
}
这让我可以做
write('table-users', { userId: '123', username: 'John Doe' }); // ✅
write('table-posts', { postId: 'abc', userId: '123', title: 'First Post' }); // ✅
但不是
write('table-users', { postId: 'abc' }); // ❌
write('table-posts', { userId: 'abc' }); // ❌
到目前为止,还不错。
但是,现在我希望能够构造一个类型(类似于函数),该类型采用需要作为表名的属性,并且该类型中的另一个属性需要具有正确的项目格式。
我认为按照这些思路应该可以工作:
type Item<T extends keyof Tables> = {
table: T,
item: Tables[T],
}
并自动允许:
const userItem: Item = {
table: 'table-users',
item: {
userId: '1',
username: 'John Doe',
}
};
const postItem: Item = {
table: 'table-posts',
item: {
postId: '123',
userId: '1',
username: 'John Doe',
}
};
或者只是使用 Item
作为函数参数类型提示,但它没有,因为它总是需要显式定义表名:
const userItem: Item<'table-users'> = {
table: 'table-users',
item: {
userId: '1',
username: 'John Doe',
}
};
const postItem: Item<'table-posts'> = {
table: 'table-posts',
item: {
postId: '123',
userId: '1',
title: 'First Post',
}
};
任何线索是否可以在 TypeScript 中找到我正在寻找的东西?我认为它应该是,因为它可能是,我可能只是在做一些愚蠢的事情,但我似乎无法修复它。
相比之下,这个是有效的:
type Item = {
[T in keyof Tables]?: {
item: Tables[T]
}
}
但我希望做同样的事情,但使用 T 作为值,而不是键。
最佳答案
您可以使用 conditional types像这样:
type ItemGeneric<T> = T extends keyof Tables ? {
table: T;
item: Tables[T];
} : never;
type Item = ItemGeneric<keyof Tables>;
这将根据您为 table
设置的字符串值隐式设置 item
的类型。 Here's a small demo这在行动中。
全部归功于nmain on github感谢您告诉我这件事。
关于具有隐式属性类型的 Typescript 泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65982905/
我是一名优秀的程序员,十分优秀!