interface UserInfo {
name: string;
age: number;
email?: string;
}
function printUser(user: UserInfo) {
let info = `Name: ${user.name}, Age: ${user.age}`;
if (user.email) {
info += `, Email: ${user.email}`;
}
console.log(info);
}
TypeScript 中接口类型兼容性规则
- 属性少的类型兼容属性多的类型:如果一个类型的属性是另一个类型属性的子集,那么这个类型是兼容的。例如:
interface A {
x: number;
}
interface B {
x: number;
y: number;
}
let a: A = { x: 1 };
let b: B = { x: 1, y: 2 };
a = b; // 允许,因为 B 的属性包含 A 的所有属性
// b = a; // 不允许,因为 A 缺少 B 中的 y 属性
- 可选属性与兼容:可选属性在兼容性判断时会被忽略。例如:
interface C {
x: number;
y?: number;
}
interface D {
x: number;
}
let c: C = { x: 1 };
let d: D = { x: 1 };
c = d; // 允许,y 是可选属性,在兼容性判断时被忽略
d = c; // 也允许,因为 D 中没有 y 属性,而 C 的 y 属性是可选的
- 函数参数的双向协变:在函数类型兼容性判断时,参数类型是双向协变的。即参数类型更宽松或者更严格的函数类型都可能是兼容的。例如:
let func1 = (x: number) => x;
let func2 = (x: any) => x;
func1 = func2; // 允许,因为 any 类型比 number 类型更宽松
func2 = func1; // 也允许,因为 number 类型比 any 类型更严格
- 函数返回值的协变:函数返回值类型是协变的,即返回值类型更具体(更严格)的函数类型是兼容返回值类型更宽泛(更宽松)的函数类型。例如:
let func3 = () => ({ name: 'John' });
let func4 = () => ({ name: 'John', age: 30 });
func3 = func4; // 允许,因为 func4 的返回值类型是 func3 返回值类型的超集
// func4 = func3; // 不允许,因为 func3 的返回值类型缺少 func4 返回值中的 age 属性