面试题答案
一键面试声明方式
- 接口(interface):使用
interface
关键字声明。例如:
interface User {
name: string;
age: number;
}
- 类型别名(type alias):使用
type
关键字声明。例如:
type User = {
name: string;
age: number;
};
功能特性
- 接口(interface):
- 主要用于定义对象的形状,对对象的结构进行描述。
- 支持声明合并,即多个同名接口声明会自动合并。例如:
interface User {
name: string;
}
interface User {
age: number;
}
// 此时 User 接口有 name 和 age 属性
- 类型别名(type alias):
- 不仅可以用于定义对象类型,还能定义基本类型别名、联合类型、交叉类型等。例如:
type StringOrNumber = string | number;
type UserInfo = { name: string } & { age: number };
- 不支持声明合并。
可扩展性
- 接口(interface):扩展性较好,通过声明合并可以在不同地方为同一个接口添加新属性。例如在大型项目中,不同模块可能需要对同一个基础接口进行扩展。
- 类型别名(type alias):一旦定义,无法像接口那样通过声明合并进行扩展,如需扩展,需重新定义新的类型别名。
实际项目场景
- 对象形状定义:
- 选择接口:在定义 API 响应数据的结构时,例如定义用户信息接口。因为 API 响应数据结构相对固定,且可能在不同模块有扩展需求,接口的声明合并特性方便扩展。
interface UserResponse {
id: number;
name: string;
}
// 其他模块可扩展
interface UserResponse {
email: string;
}
- 选择类型别名:如果只是简单定义一个一次性使用的对象类型,例如函数内部使用的临时对象类型。使用类型别名定义更简洁。
function printUser(user: { name: string; age: number }) {
console.log(user);
}
// 也可写成
type User = { name: string; age: number };
function printUser(user: User) {
console.log(user);
}
- 联合类型与交叉类型:
- 选择类型别名:在定义函数参数可以接受多种类型时,使用类型别名定义联合类型很方便。例如一个函数可以接受字符串或数字作为参数。
type StringOrNumber = string | number;
function printValue(value: StringOrNumber) {
console.log(value);
}
- 基本类型别名:
- 选择类型别名:为基本类型定义别名,提高代码可读性。比如在处理颜色值时,定义一个
Color
类型别名。
- 选择类型别名:为基本类型定义别名,提高代码可读性。比如在处理颜色值时,定义一个
type Color = string;
function setColor(color: Color) {
// 设置颜色逻辑
}
React 组件 props 类型定义
- 使用接口定义 props 类型:
import React from 'react';
interface ButtonProps {
text: string;
onClick: () => void;
disabled?: boolean;
}
const Button: React.FC<ButtonProps> = ({ text, onClick, disabled = false }) => {
return (
<button disabled={disabled} onClick={onClick}>
{text}
</button>
);
};
export default Button;
- 使用类型别名定义 props 类型:
import React from 'react';
type ButtonProps = {
text: string;
onClick: () => void;
disabled?: boolean;
};
const Button: React.FC<ButtonProps> = ({ text, onClick, disabled = false }) => {
return (
<button disabled={disabled} onClick={onClick}>
{text}
</button>
);
};
export default Button;
分析哪种方式更优及其原因
在这个简单的 React 组件场景下,接口和类型别名都能很好地完成任务。但如果考虑项目规模和未来扩展性:
- 接口更优:如果项目规模较大,并且预计
ButtonProps
可能在不同模块有扩展需求,接口的声明合并特性可以让代码更易于维护。例如后续可能需要添加loading
属性,在不同模块通过声明合并就能轻松实现。 - 类型别名更优:如果项目规模较小,并且
ButtonProps
不会有扩展需求,类型别名定义相对更简洁,且它能灵活定义联合类型等特性,在某些复杂类型需求场景下有优势。 总的来说,没有绝对的优劣,需根据项目实际情况选择。