英文:
Union type mapped to an object with single key
问题
有没有一种方法可以创建一个只有一个键,该键是字符串联合类型中的一个字符串的对象类型?
示例:
type Key = "a" | "b" | "c"
const result = {
a: "hello there"
}
const result2 = {
b: "General Kenobi"
}
const result3 = {
c: 2137
}
// 所有上面的类型在映射之后应该是正确的
const wrongType = {
a: "hello there";
b: "General Kenobi";
}
const wrongType2 = {};
// 这些应该是错误的,因为要么不是只有一个键的对象,要么根本没有键
英文:
Is there a way to create an object type with a single key that is one of the strings from the string union type?
Example:
type Key = "a" | "b" | "c"
const result = {
a: "hello there"
}
const result2 = {
b: "General Kenobi"
}
const result3 = {
c: 2137
}
// All types above should be correct after mapping
const wrongType = {
a: "hello there";
b: "General Kenobi";
}
const wrongType2 = {};
// Those should be wrong because either it's not a single-key object, or it doesn't have keys at all
答案1
得分: 1
你可以使用映射类型
来实现这个。
type Keys = "a" | "b" | "c";
type T = {
[key in Keys]: { [k in key]: unknown } & {
[k in Exclude<Keys, key>]?: never;
};
}[Keys];
因此,我们生成了一个类型,它是三个对象的联合类型,其中每个对象明确说明如果一个属性存在,其他属性就不应存在。所生成的类型如下:
type T =
| { a: unknown; b?: undefined; c?: undefined }
| { b: unknown; a?: undefined; c?: undefined }
| { c: unknown; a?: undefined; b?: undefined };
注意:仅仅使用以下代码:
type T = {
[key in Keys]: { [k in key]: unknown }
}[Keys];
是不会起作用的,因为没有辨别属性的联合类型不执行多余属性检查。
英文:
You can achieve this using mapped types
.
type Keys = "a" | "b" | "c";
type T = {
[key in Keys]: { [k in key]: unknown } & {
[k in Exclude<Keys, key>]?: never;
};
}[Keys];
So, we generate a type that is a union of three objects where each object explicitly states that if one property is present others should not be present. So, the generated type is the following:
type T =
| { a: unknown; b?: undefined; c?: undefined }
| { b: unknown; a?: undefined; c?: undefined }
| { c: unknown; a?: undefined; b?: undefined };
<br>
NOTE: Just doing the following:
type T = {
[key in Keys]: { [k in key]: unknown }
}[Keys];
would not work because Unions without discriminant properties do not perform excess property checking.
答案2
得分: 0
使用名为ts-xor的库可以实现这一点:
import { XOR } from 'ts-xor'
let test: <A, B>
type Key = XOR<{ a: string }, XOR<{ b: string }, { c: string }>>
// OK!
const result: Key = {
a: "hello there"
}
// OK!
const result2: Key = {
b: "General Kenobi"
}
// OK!
const result3: Key = {
c: 2137
}
// Error due to no matching type
const wrongType: Key = {
a: "hello there",
b: "General Kenobi",
}
// Also errors
const wrongType2: Key = {}
英文:
One way to do that is using the library called ts-xor:
import { XOR } from 'ts-xor'
let test: <A, B>
type Key = XOR<{ a: string }, XOR<{ b: string }, { c: string }>>
// OK!
const result: Key = {
a: "hello there"
}
// OK!
const result2: Key = {
b: "General Kenobi"
}
// OK!
const result3: Key = {
c: 2137
}
// Error due to no matching type
const wrongType: Key = {
a: "hello there",
b: "General Kenobi",
}
// Also errors
const wrongType2: Key = {}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论