工作中用了多年的typeScript,自认为是会使用的,每天就像吃饭喝水一样的在用。但是一旦面试,问到的一些相关的问题,哎,我怎么好像说不清楚了呢。所以还是需要系统的学习总结一下常见的问题。
1、Interface 接口
描述对象形状的语法结构
TypeScript
interface User{
readonly id: number;
name: string;
email: string;
avatarUrl?:string //可选属性
}
1.1、接口的拓展 extends
通过extends继承其他接口,形成层级结构
TypeScript
interface Admin extends User{
role: 'admin';
level: 'super' | 'admin' | 'user';
}
const myAdmin: Admin = {
id: 1,
name: 'John',
email: 'john@example.com',
role: 'admin',
level: 'super',
}
1.2、interface 和 type 的区别
|------|------------|---------------|
| | interface | type |
| 用途 | 定义对象或类结构契约 | 为任意类型创建别名 |
| 拓展方式 | extends | 交叉类型& |
| 声明合并 | 支持 | 不支持 |
| 应用范围 | 对象、函数、类 | 任意类型(包括联合、元组) |
1.3、 声明合并
多个同名interface会自动合并属性
TypeScript
//声明合并
interface Window {
title: string;
}
interface Window {
name: string;
}
interface Window {//实际合并结果
title: string;
name: string;
}
typescript可跨文件声明
拓展全局对象或库类型非常实用
1.4、type
可定义联合类型、元组等复杂类型结构
TypeScript
//type
type Status = 'success' | 'pending' | 'failed'
type PointData = [number, number]
interface无法定义这类非对象结构
type更灵活可搭配交叉和映射类型使用
2、拓展接口 extends
TypeScript
interface Person {
name: string;
age: number;
}
interface Employee extends Person {
employeeId: number;
department: string;
}
const employee: Employee = {
name: "john",
age: 35,
employeeId: 1,
department: "Engineering",
};
2.1 类型兼容性与多态
TypeScript
function greetPerson(person: Person): void {
console.log(`hello, ${person.name}`);
}
greetPerson(employee);
2.2 拓展多个接口
TypeScript
interface Clickable {
onClick(e: MouseEvent): void;
}
interface Dragable {
onDrag(e: DragEvent): void;
}
interface Button extends Clickable, Dragable {
label: string;
}
const btn: Button = {
onClick: () => {},
onDrag: () => {},
label: "hello",
};
3、联合类型
一个值可以属于 多种类型之一
TypeScript
let myVal: string | number;
3.1类型收窄
TypeScript
//1、typeof 类型守卫
function formatId(id: string | number) {
if (typeof id === "string") {
return id.toUpperCase();
} else {
return id.toFixed(2);
}
}
//2、in操作符守卫
interface Admin {
name: string;
privileges: string[];
}
interface Customer {
name: string;
credit: number;
}
type Users = Admin | Customer;
function displayUserInfo(user: Users){
if("privileges" in user){
console.log(user.privileges.join())
}
if("credit" in user){
console.log(user.credit)
}
}
//3、可辨识联合 switch语句进行类型推断
interface Circle{
kind: 'circle',
radius: number
}
interface Square{
kind: 'square',
sideLength: number
}
type Shape = Circle | Square
4、交叉类型
&连接,同时拥有所有被合并类型的属性
TypeScript
type TypeA = { a: string };
type TypeB = { b: number };
type CombineType = TypeA & TypeB;
const obj: CombineType = { a: "123", b: 123 };
type ImpossibleType = string & number //never
交叉类型 VS 接口拓展
|------|-------------------------|--------------------------------|
| 特性 | interface extends | type A & B |
| 语义 | 继承 | 组合 |
| 场景 | 层次结构 Admin extends User | 混入、功能聚合 Draggable & Clickable |
| 来源限制 | 仅适用于接口 | 任意类型组合 |
5、范型
TypeScript
//泛型 <T>声明变量
function identify<T>(arg: T): T {
return arg;
}
//类型推断
let output = identify<string>("string");
let anotherOutput = identify(123);
5.1 范型接口
TypeScript
interface ApiResponse<T> {
data: T;
status: "success" | "error";
message?: string;
}
const userResponse: ApiResponse<User> = {
data: { id: 1, name: "john" },
status: "success",
};
5.2 范型类
TypeScript
class DataStore<T> {
private data: T[] = [];
addItem(item: T): void {
this.data.push(item);
}
getItems(): T[] {
return this.data;
}
}
const numberStore = new DataStore<number>();
numberStore.addItem(123);
6、范型约束
TypeScript
//局限
function logLength<T>(arg: T) {
console.log(arg.length); //报错
}
extends添加约束
TypeScript
interface LenghtWise {
length: number;
}
function logLength1<T extends LenghtWise>(arg: T) {
console.log(arg.length);
}
进阶keyof访问对象属性
TypeScript
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
const person1 = { name: "john", age: 35 };
getProperty(person1, "name");
getProperty(person1, "age");
7、实用工具类型
TypeScript
//Partial<T> 让一切变为可选,等价于所有属性打问号
//场景:处理部分更新数据结构
interface User1 {
id: number;
username: string;
email: string;
}
function updateUser(id: number, field: Partial<User1>) {}
updateUser(1, { username: "hello" });
TypeScript
//Readonly<T>
//将T所有属性变为只读
//配置对象或状态管理中防止被修改
interface AppConfig {
apiUrl: string;
theme: "light" | "dark";
}
const config: Readonly<AppConfig> = {
apiUrl: "http://abc.com",
theme: "dark",
};
config.theme = "light"; //报错
TypeScript
//Pick<T,K>
//从T中挑选部分属性K生成新类型
//场景:提取轻量级视图对象
type UserPreview = Pick<User, "id" | "name">;
TypeScript
//Omit<T,K>
//从T中排除属性K生成新类型
//场景过滤敏感信息或不必要信息
type UserPreview1 = Omit<User, "password">;
//其他
// Required<T>:将所有属性改为必填
//Record<K,T>:创建键值映射类型
//Exclude<T,U>:排除联合类型的某些成员
//ReturnType<T>:提取函数返回类型
8、类
TypeScript
//类 定义了对象的属性、方法
class Player {
username: string;
health: number;
isOnline: boolean;
constructor(username: string) {
this.username = username;
this.health = 100;
this.isOnline = true;
console.log(`welcome ${this.username}`);
}
attack(target: Player): void {
if (!this.isOnline || !target.isOnline) return;
console.log(`${this.username} attack ${target.username}`);
}
disconnect(): void {
this.isOnline = false;
console.log(`${this.username} has disconnected.`);
}
}
//创建与使用
const palyer1 = new Player("Alice");
const palyer2 = new Player("Bob");
palyer1.attack(palyer2);
palyer2.disconnect();
//new关键字用于实例化对象
//constructor 会在创建对象时自动执行
//通过this访问属性和方法
8.1访问修饰符
TypeScript
//public:公开访问,默认修饰符,可在任何位子访问,类内、实例外、子类
class Greeter {
public message: string;
constructor(message: string) {
this.message = message;
}
}
const g = new Greeter("hello");
g.message;
//private: 仅限内部访问,实例或子类无法访问,用于隐藏实现细节或中间状态
class BankAccount {
private balance: number = 0;
constructor(initial: number) {
if (this.isValid(initial)) this.balance = initial;
}
deposit(amount: number) {
if (this.isValid(amount)) this.balance += amount;
}
private isValid(amount: number): boolean {
return amount > 0;
}
}
const acc = new BankAccount(100);
acc.deposit(50);
acc.balance; // 报错
//protected: 类及其子类内部访问,用于子类拓展父类功能时保留访问能力
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Dog extends Animal {
bark() {
console.log(`woof! I am ${this.name}`);
}
}
const d = new Dog("buddy");
d.bark();
d.name; // 报错
9、抽象类
TypeScript
//半成品,定义了通用实现和必须实现额接口
abstract class Employee {
public name: string;
constructor(name: string) {
this.name = name;
}
public getProfile(): string {
return `Employee ${this.name}`;
}
//抽象方法,无实现,子类必须实现
public abstract caculateBonus(salary: number): number;
}
//抽象类不能直接实例化
//子类必须实现所有抽象方法,否则编译器报错
//抽象类可以包含构造函数和普通方法
来源: 来源