英文:
Typescript template literal mapped type
问题
以下是您要翻译的代码部分:
我正在开发一个转换器应用程序,一直在尝试着使用模板文字作为映射类型的对象类型。
我想要做的是:在下面的代码中对`formulas`对象进行类型定义,该对象将包含将摄氏度转换为开尔文、开尔文转换为华氏度等的所有公式。
我能够像这样对其进行类型定义:
```typescript
type ConversionsOptions<T extends TemperatureUnit> = {
key: ConversionCategoryType;
items: Array<ConversionItem<T>>;
formulas: {
[U in `${T}_to_${T}`]: (n: number) => number;
};
};
用于转换的对象看起来是这样的:
const temperatureCategory: ConversionsOptions<
'celsius' | 'farenheit' | 'kelvin'
> = {
key: 'temperature',
items: [
{
key: 'celsius',
},
{
key: 'kelvin',
},
{
key: 'farenheit',
},
],
formulas: {
celsius_to_kelvin: (n: number) => n + 273.15,
celsius_to_farenheit: (n: number) => n * (9 / 5) + 32,
kelvin_to_farenheit: (n: number) => (n - 273.15) * (9 / 5) + 32,
kelvin_to_celsius: (n: number) => n - 273.15,
farenheit_to_kelvin: (n: number) => (n - 32) * (5 / 9) + 273.15,
farenheit_to_celsius: (n: number) => (n - 32) * (5 / 9),
},
};
因此,使用这种类型,公式对象的索引是正确的,但允许celsius_to_celsius
、farenheit_to_farenheit
和kelvin_to_kelvin
出现在对象中。
我尝试使用排除(Exclude
)实用程序类型,如下所示:
[U in `${T}_to_${Exclude<T, U>}`]: (n: number) => number;
在映射类型中,但不幸的是,它不起作用。
有没有什么想法可以解决这个问题?
<details>
<summary>英文:</summary>
i'm working on a converter app and have been trying ~ for a while now ~ to successfuly type an object with template literals as a mapped type.
What I want to do: type the `formulas` object in the code below, that would contain every formula to convert celsius to kelvin, kelvin to farenheit, etc.
I was able to type it like that :
```typescript
type ConversionsOptions<T extends TemperatureUnit> = {
key: ConversionCategoryType;
items: Array<ConversionItem<T>>;
formulas: {
[U in `${T}_to_${T}`]: (n: number) => number;
};
};
The object for the conversions looks like that :
const temperatureCategory: ConversionsOptions<
'celsius' | 'farenheit' | 'kelvin'
> = {
key: 'temperature',
items: [
{
key: 'celsius',
},
{
key: 'kelvin',
},
{
key: 'farenheit',
},
],
formulas: {
celsius_to_kelvin: (n: number) => n + 273.15,
celsius_to_farenheit: (n: number) => n * (9 / 5) + 32,
kelvin_to_farenheit: (n: number) => (n - 273.15) * (9 / 5) + 32,
kelvin_to_celsius: (n: number) => n - 273.15,
farenheit_to_kelvin: (n: number) => (n - 32) * (5 / 9) + 273.15,
farenheit_to_celsius: (n: number) => (n - 32) * (5 / 9),
},
};
So with this type, the formula's object indexes are correct but it allows celsius_to_celsius, farenheit_to_farenheit and kelvin_to_kelvin to be in the object.
I tried to use Exclude utility type like this :
[U in `${T}_to_${Exclude<T, U>}`]: (n: number) => number;
in the mapped type, but unfortunately, it doesn't work.
Any ideas how this problem could be solved ?
答案1
得分: 2
If we use key remapping, we can use Exclude
:
type ConversionsOptions<T extends TemperatureUnit> = {
formulas: {
[U in T as `${U}_to_${Exclude<T, U>}`]: (n: number) => number;
};
};
We can make a type that gets the duplicates utilizing distributive conditional types:
type Duplicates<T extends string> = T extends T ? `${T}_to_${T}` : never;
and then simply omit the dupes from the mapped type:
type ConversionsOptions<T extends TemperatureUnit> = {
formulas: Omit<{
[U in `${T}_to_${T}`]: (n: number) => number;
}, Duplicates<T>>;
};
You could also inline the type if you don't want to create another type that's only used once:
type ConversionsOptions<T extends TemperatureUnit> = {
formulas: Omit<{
[U in `${T}_to_${T}`]: (n: number) => number;
}, T extends T ? `${T}_to_${T}` : never>;
};
英文:
If we use key remapping, we can use Exclude
:
type ConversionsOptions<T extends TemperatureUnit> = {
formulas:{
[U in T as `${U}_to_${Exclude<T, U>}`]: (n: number) => number;
};
};
We can make a type that gets the duplicates utilizing distributive conditional types:
type Duplicates<T extends string> = T extends T ? `${T}_to_${T}` : never;
and then simply omit the dupes from the mapped type:
type ConversionsOptions<T extends TemperatureUnit> = {
formulas: Omit<{
[U in `${T}_to_${T}`]: (n: number) => number;
}, Duplicates<T>>;
};
You could also inline the type if you don't want to create another type that's only used once:
type ConversionsOptions<T extends TemperatureUnit> = {
formulas: Omit<{
[U in `${T}_to_${T}`]: (n: number) => number;
}, T extends T ? `${T}_to_${T}` : never>;
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论