打字稿:如何创建一个新的 key/value 对类型,它的形状与对象数组中的一个对象完全相同?
Typescript: How to create a new key/value pair type that is exactly in the same shape as one of the objects in an array of objects?
我有以下数据:
const pets = [
{
type: 'cat',
name: 'penny'
},
{
type: 'dog',
name: 'Fido'
},
{
type: 'fish',
name: 'Nemo'
}
];
宠物只有在完全符合这 3 种形状(即键和值必须匹配)中的任何一种时才应被视为有效。例如,这是一个有效的宠物:
{
type: 'dog',
name: 'Fido'
}
这些不是:
{
age: 'dog',
name: 'Fido'
},
和
{
type: 'dog',
name: 'Sammy'
},
等..
我的实际对象比这个大很多,所以我不想手动定义这个类型。如何动态完成?
我试过了,但没有用:
type Pet = {
[key in keyof typeof pets]: typeof pets[key];
};
您需要在 pets
上使用 an as const
assertion 来告诉打字稿推断它可以推断出的最具体的类型。否则 pets
只是键入 { type: string, name: string }[]
,这没有帮助。
const pets = [
{
type: 'cat',
name: 'penny'
},
{
type: 'dog',
name: 'Fido'
},
{
type: 'fish',
name: 'Nemo'
}
] as const;
现在 pets
输入为:
const pets: readonly [{
readonly type: "cat";
readonly name: "penny";
}, {
readonly type: "dog";
readonly name: "Fido";
}, {
readonly type: "fish";
readonly name: "Nemo";
}]
请注意三个特定对象如何具有不同的特定字符串。
现在 Pet
类型就是:
type Pet = typeof pets[number]
/*
{
readonly type: "cat";
readonly name: "penny";
} | {
readonly type: "dog";
readonly name: "Fido";
} | {
readonly type: "fish";
readonly name: "Nemo";
}
*/
通过 number
索引数组类型得到所有数组成员类型的联合。在这种情况下,每种特定类型的宠物。
现在一切如你所愿:
const fido: Pet = { // works
type: 'dog',
name: 'Fido'
}
const bad1: Pet = { // error because Nemo is a fish
type: 'cat',
name: 'Nemo'
}
const bad2: Pet = { // error because penny is a cat
type: 'dog',
name: 'penny'
}
您还可以使用 Record
和 enum
来固定具有特定值的类型。我不知道这是否正是你想要的,但你可以试试。
// Define the keys here they will make sure that nothing
// other then these keys exist here.
enum Keys {
TYPE = "type",
NAME = "name",
}
// Create a Record type that can only take this key but any string value
type Pet = Record<Keys, string>;
const pets: Pet[] = [
{
type: "cat",
name: "penny",
},
{
type: "dog",
name: "Fido",
},
{
type: "fish",
name: "Nemo",
},
];
// Valid
const pet: Pet = {
type: "cat",
name: "fido",
};
// Invalid
const invalidPet: Pet = {
age: 'dog',
name: 'Fido'
};
再次注意,键定义了您可以将什么作为键,而值不受限制,它们可以是任何东西。
如果您也想限制值(不是有效的情况,因为它没有任何意义),您也可以为此创建一个 enum
。
我有以下数据:
const pets = [
{
type: 'cat',
name: 'penny'
},
{
type: 'dog',
name: 'Fido'
},
{
type: 'fish',
name: 'Nemo'
}
];
宠物只有在完全符合这 3 种形状(即键和值必须匹配)中的任何一种时才应被视为有效。例如,这是一个有效的宠物:
{
type: 'dog',
name: 'Fido'
}
这些不是:
{
age: 'dog',
name: 'Fido'
},
和
{
type: 'dog',
name: 'Sammy'
},
等..
我的实际对象比这个大很多,所以我不想手动定义这个类型。如何动态完成?
我试过了,但没有用:
type Pet = {
[key in keyof typeof pets]: typeof pets[key];
};
您需要在 pets
上使用 an as const
assertion 来告诉打字稿推断它可以推断出的最具体的类型。否则 pets
只是键入 { type: string, name: string }[]
,这没有帮助。
const pets = [
{
type: 'cat',
name: 'penny'
},
{
type: 'dog',
name: 'Fido'
},
{
type: 'fish',
name: 'Nemo'
}
] as const;
现在 pets
输入为:
const pets: readonly [{
readonly type: "cat";
readonly name: "penny";
}, {
readonly type: "dog";
readonly name: "Fido";
}, {
readonly type: "fish";
readonly name: "Nemo";
}]
请注意三个特定对象如何具有不同的特定字符串。
现在 Pet
类型就是:
type Pet = typeof pets[number]
/*
{
readonly type: "cat";
readonly name: "penny";
} | {
readonly type: "dog";
readonly name: "Fido";
} | {
readonly type: "fish";
readonly name: "Nemo";
}
*/
通过 number
索引数组类型得到所有数组成员类型的联合。在这种情况下,每种特定类型的宠物。
现在一切如你所愿:
const fido: Pet = { // works
type: 'dog',
name: 'Fido'
}
const bad1: Pet = { // error because Nemo is a fish
type: 'cat',
name: 'Nemo'
}
const bad2: Pet = { // error because penny is a cat
type: 'dog',
name: 'penny'
}
您还可以使用 Record
和 enum
来固定具有特定值的类型。我不知道这是否正是你想要的,但你可以试试。
// Define the keys here they will make sure that nothing
// other then these keys exist here.
enum Keys {
TYPE = "type",
NAME = "name",
}
// Create a Record type that can only take this key but any string value
type Pet = Record<Keys, string>;
const pets: Pet[] = [
{
type: "cat",
name: "penny",
},
{
type: "dog",
name: "Fido",
},
{
type: "fish",
name: "Nemo",
},
];
// Valid
const pet: Pet = {
type: "cat",
name: "fido",
};
// Invalid
const invalidPet: Pet = {
age: 'dog',
name: 'Fido'
};
再次注意,键定义了您可以将什么作为键,而值不受限制,它们可以是任何东西。
如果您也想限制值(不是有效的情况,因为它没有任何意义),您也可以为此创建一个 enum
。