在初始化值时,可以使用类型实用程序Partial<Type>
来指示尚未定义属性:
let user: Partial<Person> = {};
在初始化属性值之后,TypeScrip将正确地推断它们确实存在:
user.age = 22;
user.name = "Dave";
user.city = "NY";
const doubleAge = user.age * 2; // Ok
const lowercaseCity = user.city.toLowerCase(); // Ok
const uppercaseName = user.name.toUpperCase(); // Ok
TS Playground个
但是,如果您没有初始化其中一个属性值,则在try 使用该属性值时,TypeScrip将发出错误诊断:
let user: Partial<Person> = {};
user.age = 22;
const doubleAge = user.age * 2; // Ok
const lowercaseCity = user.city.toLowerCase(); /* Error
~~~~~~~~~
'user.city' is possibly 'undefined'.(18048) */
const uppercaseName = user.name.toUpperCase(); /* Error
~~~~~~~~~
'user.name' is possibly 'undefined'.(18048) */
TS Playground个
在某些情况下,推理仍然不够-例如,当值需要用作需要Person
的函数的参数时:
declare function doSomethingWithPerson(person: Person): void;
let user: Partial<Person> = {};
user.age = 22;
user.name = "Dave";
user.city = "NY";
doSomethingWithPerson(user); /* Error
~~~~
Argument of type 'Partial<Person>' is not assignable to parameter of type 'Person'.
Property 'name' is optional in type 'Partial<Person>' but required in type 'Person'.(2345) */
TS Playground个
在这些情况下,您可以创建一个名为type guard的函数,该函数将在运行时进行判断,以确保类型满足声明的期望.用户定义的类型保护是返回类型为type predicate的函数:
function isPerson<T extends Record<PropertyKey, unknown>>(
p: T,
): p is T & Person {
return (
typeof p.age === "number" &&
typeof p.city === "string" &&
typeof p.name === "string"
);
}
另请参阅手册:generics
然后您可以在使用前判断user
是否确实符合Person
的定义,以避免错误:
let user: Partial<Person> = {};
user.age = 22;
user.name = "Dave";
user.city = "NY";
if (isPerson(user)) {
doSomethingWithPerson(user); // Ok
} else {
// Handle the other case here
}
TS Playground个