记录每天自我学习转前端的碎碎念,仅作加强记忆的笔记和自我监督打卡使用。
泛型
通常在定义函数或者接口时,如果一个参数或者属性的数据类型是明确的,比如说是string或者number,则定义时很容易
function add(a:number, b:number):number {
return a+b;
}
interface Person {
name : string
}
但是如果一个参数或者属性的数据类型并不清楚,我不知道是string还是number,这种场景通常使用泛型来解决,泛型及只有使用的时候才确定其类型
const printFun = <T>(value: T): T => {
console.log(value);
return value;
};
printFun(233);
// 可以设置默认值
interface Person<T = string> {
address:T
}
function demo<T>(person:Person<T>) {
console.log(person.address)
}
demo<string>({address:'中国'})
demo({address:'中国'}) // 也可以
note:这里由于参数person是:Person<T>类型,则表示函数demo是一个泛型函数,所以也需要定义demo<T>
泛型还可以通过extends进行约束扩展
// dmeo1
interface Person<J, K> {
name: J;
age: K;
}
const printFun = <T extends Person<string, number>, S>(
person: T,
msg: S
): S => {
console.log(person.age);
console.log(person.name);
return msg;
};
printFun({ name: "sunny", age: 18 }, "success");
// dmeo2
function logLength<T extends { length: number }>(arg: T): T {
console.log(arg.length);
return arg;
}
logLength("string"); // 正确
logLength({ length: 5 }); // 正确
logLength(123); // 错误:数字没有length属性
// demo3(和demo2效果一致)
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length);
return arg;
}
注意:静态成员不能使用类的类型参数
class GenericClass<T> {
static defaultValue: T; // 错误:静态成员不能使用类的类型参数
}
TypeScript内置了多个实用的泛型工具类型:
1.Partial 是一个内置工具类型,用于将一个对象类型的所有属性变为可选属性。它通过映射类型实现,为每个属性添加 ? 修饰符,使其变为可选属性
interface User {
id: number;
name: string;
email: string;
}
// 使用 Partial 创建所有属性可选的新类型
type PartialUser = Partial<User>;
/* 等价于:
type PartialUser = {
id?: number;
name?: string;
email?: string;
}
*/
2.Readonly: 使所有属性变为只读
type ReadonlyUser = Readonly<User>;
3.Record: 键值对映射
type UserPreview = Record<"id" | "name" | "email", string>;
项目应用1
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
async function fetchData<T>(url: string): Promise<ApiResponse<T>> {
const response = await fetch(url);
return response.json();
}
interface User {
id: number;
name: string;
}
fetchData<User>("/api/user").then(response => {
console.log(response.data.name); // 类型安全
});
项目应用2
interface User {
id:string,
name:string
}
interface Repository<T, ID> {
findById(id: ID): Promise<T | null>;
save(entity: T): Promise<T>;
findAll(): Promise<T[]>;
}
class UserRepository implements Repository<User, number> {
findById(id: number): Promise<User> {
return Promise.resolve({
id:'12',
name:'李白'
})
}
save(entity: User): Promise<User> {
return Promise.resolve({
id:'12',
name:'李白'
})
}
findAll(): Promise<User[]> {
return Promise.resolve([{
id:'12',
name:'李白'
}])
}
}