Typescript 类型脚本类型是否依赖于属性名称?

Typescript 类型脚本类型是否依赖于属性名称?,typescript,Typescript,这是一个有点奇怪的问题,但我仍然对它的可能性感到好奇 我有一个来自API的JSON结构,它定义了如下映射: "sizes: { "thumbnail": "xxxx", "thumbnail-width: 150, "thumbnail-height: 150, "medium: "xxx", "medium-width": 500,

这是一个有点奇怪的问题,但我仍然对它的可能性感到好奇

我有一个来自API的JSON结构,它定义了如下映射:

"sizes: {
    "thumbnail": "xxxx",
    "thumbnail-width: 150,
    "thumbnail-height: 150,
    "medium: "xxx",
    "medium-width": 500,
    "medium-height": 500,
    ...
}
名称在某种程度上是预定义的,但实际上不是

我的问题是,是否可以将任何以-width或-height结尾的属性定义为number,而将其他所有属性定义为string。类似正则表达式(.*)-(宽度|高度):数字


TypeScript可以做各种神奇的事情,但它能做这样的事情吗?

从TypeScript 4.1开始,可以使用文字类型。 例如:

type AddSuffixToEachProps<T, Suffix extends string, Value extends any> = T & {
    [P in keyof T as `${string & P}-${Suffix}`]: Value
}
输入AddSuffixToEachProps=T&{
[P在T的键中作为`${string&P}-${Suffix}`]:值
}
这是一种接受某种模式的类型,并为每个道具添加后缀

用法:

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
}
type Result=addSuffExtoeAchProps
常数测试:结果={
foo:'一些字符串',
“foo宽度”:123,//必需
吧台:['1','2','3'],
“钢筋宽度”:456//必填项
}
不,不可能

因为

索引签名参数类型必须为“字符串”或“数字”


我们现在不能将type
${string}-width
${string}-height
设置为
大小的键类型,从TS4.1开始,TypeScript中没有具体的类型(我们称之为
)来表示可分配给
属性的值。作为记录,我将其解释为:任何字符串键都是可以接受的;如果键以
-width
-height
结尾,则属性必须是
数字
;否则它必须是
字符串
。没有要求这些密钥必须显示为三元组;例如,如果
“键”
是键,则不要求存在
“键高”
“键宽”

也许当被寻址时(如果被合并的话),您将能够使用
`${string}-width`
格式的“模式”模板文本(如中实现的)作为键。现在你不能

目前,对于适当的
K
,您只能将您的限制表示为
值的形式:

type Values<K extends string> = {
  [P in K]: P extends `${string}-${"height" | "width"}` ? number : string
};
让我们试试看:

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'
})
看起来不错<接受代码>大小
,但
不良大小
会导致类型不正确的属性出错


当然,我们使用泛型的事实意味着您必须将泛型类型参数
K
拖到您想要强制执行此限制的任何地方。如果将其用于整个代码库,可能会变得笨拙。相反,您可能只想使用
来验证传入的对象文本,然后在操作它们时,将其扩展到TypeScript可以表示的最接近的特定类型,如属性为
string | number
的类型:

type WideValues = { [k: string]: string | number };
const wideValues: WideValues = sizes; // okay
因此,您使用
进行验证,然后使用
宽值
进行操作



如果前缀是预先知道的,但问题表明它们不是(或者在任何情况下“不是真的”)。这种想法
Record`会起作用,但不会。非常酷,但只有在编译时知道键时才起作用,在这种情况下,我还可以定义width和height属性。不要认为这可以解释为
typet={[x in`${string}-width` |${string}-height`]:number}
编译得很好,但不知何故解析为
t={}
,这对我来说似乎有问题。是的,对我来说也有问题。我认为这个功能还没有完全被支持。是的,这是目前已知的问题
type WideValues = { [k: string]: string | number };
const wideValues: WideValues = sizes; // okay