摘要
TypeScript使用起来很麻烦,但是效果却很香!
一、类型复用不足
TypeScript允许我们使用type
和interface
来定义类型。
type
定义的类型可以通过交叉类型(&
)来进行复用,而interface
定义的类型则可以通过继承(extends
)来实现复用。
复用type
定义的类型:
type Point = {
x: number;
y: number;
};
type Coordinate = Point & {
z: number;
};
复用interface
定义的类型:
interface Point {
x: number;
y: number;
};
interface Coordinate extends Point {
z: number;
}
interface
复用type
定义的类型:
type Point = {
x: number;
y: number;
};
interface Coordinate extends Point {
z: number;
}
type
复用interface
定义的类型:
interface Point {
x: number;
y: number;
};
type Coordinate = Point & {
z: number;
};
二、工具类型Omit与
Pick
例如,有一个已有的类型Props
需要复用,但不需要其中的属性c
。在这种情况下,团队成员会重新定义Props1
,仅包含Props
中的属性a
和b
,同时添加新属性e
。
interface Props {
a: string;
b: string;
c: string;
}
interface Props1 {
a: string;
b: string;
e: string;
}
我们可以利用TypeScript提供的工具类型Omit
来更高效地实现这种复用。
interface Props {
a: string;
b: string;
c: string;
}
interface Props1 extends Omit<Props, 'c'> {
e: string;
}
工具类型Pick
也可以用于实现此类复用。
interface Props {
a: string;
b: string;
c: string;
}
interface Props1 extends Pick<Props, 'a' | 'b'> {
e: string;
}
三、处理含有不同类型元素的数组
我们不知道如何定义含有不同类型元素的数组,通常会选择使用any[]
,但这会带来类型安全问题,元组是处理这种情况的理想选择。通过元组,我们可以在一个数组中包含不同类型的元素,同时保持每个元素类型的明确性。
function useMyHook(): [string, number] {
return ['示例文本', 42];
}
function MyComponent() {
const [text, number] = useMyHook();
console.log(text); // 输出字符串
console.log(number); // 输出数字
return null;
}
四、处理参数数量和类型不固定的函数
通过函数重载,我们可以在同一函数名下定义多个函数实现,根据不同的参数类型、数量或返回类型进行区分。
function greet(name: string): string;
function greet(age: number): string;
function greet(value: any): string {
if (typeof value === "string") {
return `Hello, ${value}`;
} else if (typeof value === "number") {
return `You are ${value} years old`;
}
}
对于箭头函数,虽然它们不直接支持函数重载,但我们可以通过定义函数签名的方式来实现类似的效果。
type GreetFunction = {
(name: string): string;
(age: number): string;
};
const greet: GreetFunction = (value: any): string => {
if (typeof value === "string") {
return `Hello, ${value}`;
} else if (typeof value === "number") {
return `You are ${value} years old.`;
}
return '';
};
五、组件属性定义
我们在定义组件属性时既可以使用type
也可以使用interface
。
由于同名接口会自动合并,而同名类型别名会冲突,我推荐使用interface
定义组件属性。这样,使用者可以通过declare module
语句自由扩展组件属性,增强了代码的灵活性和可扩展性。
interface UserInfo {
name: string;
}
interface UserInfo {
age: number;
}
const userInfo: UserInfo = { name: "张三", age: 23 };
总结
做项目还是建议使用js,效率高。做产品推荐使用ts,精打细磨。