大佬教程收集整理的这篇文章主要介绍了TypeScript 类型依赖于属性名称?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
这是一个有点奇怪的问题,但我仍然对它的可能性感到好奇。
我有一个来自 API 的 JsON 结构,它定义了这样的地图:
"sizes: {
"thumbnail": "xxxx","thumbnail-wIDth: 150,"thumbnail-height: 150,"medium: "xxx","medium-wIDth": 500,"medium-height": 500,...
}
@H_419_6@
名称在某种程度上是预定义的,但实际上并非如此。
我的问题是,是否可以将任何以 -wIDth 或 -height 结尾的属性定义为数字,其他所有内容都定义为字符串。像正则表达式 (.*)-(wIDth|height): number.
TypeScript 可以做各种神奇的事情,但它可以做这样的事情吗?
现在,从 TS4.1 开始,TypeScript 中没有特定的具体类型(我们称之为 Values
)来表示可分配给该 values
属性的值。为了记录,我将其解释为:任何字符串键都是可以接受的;如果键以 -width
或 -height
结尾,则属性必须是 number
;否则它必须是一个 String
。没有要求这些键必须显示为三元组;例如,如果 "key"
是一个键,则不需要 "key-height"
或 "key-width"
存在。
也许当 microsoft/TypeScript#42192 得到解决时,您将能够使用 `${String}-width`
形式的“模式”模板文字(如在 microsoft/TypeScript#40598 中实现的)作为键。目前你不能。
针对 TS4.4 的更新:即使使用在 microsoft/TypeScript#44512 中实现的模式模板文字索引签名,您也无法为 Values
创建特定类型。您现在可以表示以 -height
或 -width
结尾的任意字符串必须为 number
的部分:
type NumericValues = {
[key: `${String}-${"height" | "width"}`]: number;
}
但是没有办法表示“其他所有东西都需要是 String
”约束……参见 microsoft/TypeScript#17867。所以以下不起作用:
type BadValues = {
[key: `${String}-${"height" | "width"}`]: number; // error! incompatible
[key: `${String}`]: String; // can't say "everything else" here
}
哦,好吧。
因此,对于适当的 Values<K>
,您只能将限制表示为 generic consTraint,形式为 K
:
type Values<K extends String> = {
[P in K]: P extends `${String}-${"height" | "width"}` ? number : String
};
如果 K
是 Values<K>
中字符串值键的集合,则每个属性值必须是 number
或 String
,具体取决于 K
{1}} 以 "-height"
/"-width"
结尾。
您可以使用辅助函数让编译器为您推断 Values<K>
,而不是被迫将值注释为类型 K
的某些具体 K
:
const asValues = <K extends String>(values: Values<K>) => values;
让我们试试吧:
const sizes = asValues({
"thumbnail": "xxxx","thumbnail-width": 150,"thumbnail-height": 150,"medium": "xxx","medium-width": 500,"medium-height": 500,}); // okay
const badSizes = asValues({
"toenail": 123,// error! Type 'number' is not assignable to type 'String'
"toenail-width": 456,"psychic": "yyy","psychic-height": "tall" // Type 'String' is not assignable to type 'number'
})
看起来不错。接受 sizes
,但 badSizes
会导致类型不正确的属性出错。
当然,我们使用泛型这一事实意味着您必须在想要强制执行此限制的任何地方拖动泛型类型参数 K
。如果用于整个代码库,这可能会变得笨拙。相反,您可能只想使用 Values<K>
来验证传入的对象文字,然后当您操作它们时,您会扩展到 TypeScript 可以表示的最接近的特定类型,例如 String
-indexable 类型,其属性为 { {1}}:
String | number
因此您使用 type WideValues = { [k: String]: String | number };
const wideValues: WideValues = sizes; // okay
进行验证,然后使用 Values<K>
进行操作。
Playground link to code
,从 typescript 4.1 开始,使用文字类型是可能的。 一个例子:
type AddSuffixToEachProps<T,Suffix extends String,Value extends any> = T & {
[P in keyof T as `${String & P}-${Suffix}`]: Value
}
这是一种接受某种模式的类型,并为每个道具添加一个后缀。
用法:
type Result = AddSuffixToEachProps<{
foo: String,bar: String[]
},'width',number>
const test: Result = {
foo: 'some String',"foo-width": 123,// required
bar: ['one','two','three'],"bar-width": 456 // required
}
,
不,这不可能。
因为
索引签名参数类型必须是“字符串”或“数字”。
以上是大佬教程为你收集整理的TypeScript 类型依赖于属性名称?全部内容,希望文章能够帮你解决TypeScript 类型依赖于属性名称?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。