1 指定某个值的类型与对象中某个特定键的值的类型相同
在 TypeScript 中,如果你想要指定某个值的类型与对象中某个特定键的值的类型相同,你可以使用映射类型和索引类型来实现这一点。这里有一个基本的步骤来完成这个任务:
- 定义一个类型来表示对象。
- 使用映射类型来创建一个新的类型,其中包含你感兴趣的键。
- 使用索引类型来访问那个键的类型。
- 将这个类型应用于你想要限制的值。
让我们通过一个例子来说明这个过程:
假设我们有一个对象 Person
,它有多个属性,其中一个属性是 age
,我们希望有一个变量 myAge
的类型就是 Person
对象中 age
键的类型。
interface Person {
name: string;
age: number;
isStudent: boolean;
}
// 创建一个映射类型,只包含我们感兴趣的键
type AgePropertyOf<T> = T extends { age: infer Age } ? Age : never;
// 现在我们可以定义一个变量,其类型为 Person 中 age 键的类型
let myAge: AgePropertyOf<Person>;
// 这里 myAge 的类型就是 number
上面的 AgePropertyOf
类型定义使用了条件类型和索引类型。T extends { age: infer Age }
是一个条件类型,它检查类型 T
是否具有一个 age
属性,如果是,则使用 infer
关键字推断出 age
属性的类型,并命名为 Age
。如果 T
不具有 age
属性,则结果类型是 never
。
然而,这种方法只适用于确切知道键名的情况。如果键名是动态的,你可以使用字符串字面量类型或者模板字面量类型来定义键名,然后使用索引类型来访问对象中对应的值类型。
例如,如果键名是动态的,你可以这样做:
type KeyOfPerson = keyof Person; // "name" | "age" | "isStudent"
function getValueByKey<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const person: Person = { name: "Alice", age: 30, isStudent: false };
const age: AgePropertyOf<Person> = getValueByKey(person, "age"); // age 的类型是 number
在这个例子中,getValueByKey
函数接受一个对象和一个键名,返回键名对应的值。由于键名 K
被限制为 T
的键,所以返回值的类型是 T[K]
,即对象 T
上由 K
指定的键的值的类型。
2 如果你想要指定一个值必须是对象中特定两个键的类型,而排除其他键。
在 TypeScript 中,如果你想要指定一个值必须是对象中特定两个键的类型,而排除其他键,你可以使用 keyof
和类型交集来实现。首先,你需要定义一个接口或类型别名来描述对象的结构,然后使用 keyof
获取所有可能的键,并通过类型交集 &
来限制到你感兴趣的那两个键。
例如,假设我们有一个如下的对象类型:
interface MyObject {
name: string;
age: number;
location: string;
}
如果我们要确保一个变量只能是 'name'
或 'age'
键,我们可以这样做:
type NameOrAge = 'name' | 'age';
function getSpecificProperty<T extends MyObject>(obj: T, key: NameOrAge): T[NameOrAge] {
return obj[key];
}
const myObj: MyObject = {
name: "Alice",
age: 30,
location: "Wonderland"
};
const nameOrAgeValue = getSpecificProperty(myObj, 'name'); // 正确
const locationValue = getSpecificProperty(myObj, 'location'); // 错误,因为 'location' 不是 NameOrAge 类型
在这个例子中,NameOrAge
是一个类型别名,它只包括 'name'
和 'age'
。getSpecificProperty
函数的第二个参数被限制为 NameOrAge
类型,这确保了你只能传入这两个键之一。
然而,如果你想使用 keyof
和类型交集来实现,可以这样:
type SpecificKey = keyof MyObject & ('name' | 'age');
function getSpecificPropertyUsingKeyOf<T extends MyObject>(obj: T, key: SpecificKey): T[SpecificKey] {
return obj[key];
}
const specificValue = getSpecificPropertyUsingKeyOf(myObj, 'name'); // 正确
const wrongKey = getSpecificPropertyUsingKeyOf(myObj, 'location'); // 错误,因为 'location' 不是 SpecificKey 类型