个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧
搭建 TS 学习环境
创建 ts-learn 文件夹,输入如下命令初始化项目。
npm init -y
安装相关依赖。
npm i -D typescript nodemon ts-node
初始化 TS 配置。
npx tsc --init
修改 package.json
文件内容 nodemon --exec ts-node index.ts
,其中 index.js 可以修改,我们想查看哪个文件的运行结果修改为哪个文件即可。
{
"name": "ts-learn",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "nodemon --exec ts-node index.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"nodemon": "^3.1.9",
"ts-node": "^10.9.2",
"typescript": "^5.8.2"
}
}
基础类型 & 引用类型
index.ts
基础类型包括 boolean, number, string, symbol, null, undefined;
引用类型包括 {} or object, [] or Array, function, Class类型;
相关使用如下:
// string 类型
const msg: string = "hello ts!";
console.log(msg);
// boolean
const bool: boolean = true;
// object
const obj: object = {};
const obj1: {} = {};
const obj2: { msg: string; num: number } = { msg: "hello", num: 1 };
const obj3: { msg: string; num?: number } = { msg: "hello" }; // ?表示可选属性
obj3.num = 1; // 可选属性可以在后面赋值
// arr
const arr: [] = [];
// 构造函数方式
const arr1: Array<string> = ["123"];
const arr2: Array<string | number> = ["123", 234];
// 字面量方式
const arr3: string[] = ["123123"];
const arr4: (string | number)[] = ["123123", 234];
函数类型
function-demo.ts
相关使用如下:
// 基本用法
function add(arg1: number, arg2: number): number {
return arg1 + arg2;
}
add(1, 2); // 3
const add1 = (arg1: number, arg2: number): number => {
return arg1 + arg2;
};
add1(1, 2); // 3
// 匿名函数
// var fn = function() {} -> const fn = () => {}
const add2: (arg1: number, arg2: number) => number = (
arg1: number,
arg2: number
) => arg1 + arg2;
add2(1, 2); // 3
// 函数重载
function handleData(x: string): string[];
function handleData(x: number): string;
function handleData(x: any): any {
if (typeof x === "string") {
return x.split("");
} else {
return x.toString().split("").join("_");
}
}
handleData("123"); // ['1', '2', '3']
handleData(123); // '1_2_3'
// handleData(true); // error 这里会报错,因为没有布尔类型的重载
// const handleData1: (x: string) => string[]; // 不能使用箭头函数重载
any、void、never、unknow
new-types.ts
相关使用如下:
// any 类型 -> es5 var -> 任意类型
let a: any;
a = 123;
a = "123";
a = true;
a = {};
a.toFixed(2);
a.join("_");
// void 类型 -> 没有类型
let b: void;
b = undefined; // 可以赋值 undefined
// b = 123; // 不能赋值其他类型
// never -> 永远不存在的类型
// unknown -> 未知的类型
let c: unknown;
c = 123;
c = "123";
c = undefined;
c = null;
// c.toFixed(2); // 这里会报错,因为 unknown 类型不能直接调用方法
// c.join("_"); // 这里会报错,因为 unknown 类型不能直接调用方法
// 这样玩是可以的,因为能保证类型的正确
if (typeof c === "number") {
c.toFixed(2);
} else if (typeof c === "object" && c instanceof Array) {
c.join("_");
}
tuple、enum
tuple_enum.ts
相关使用如下:
// tuple 元组 -> 固定类型 + 长度的数组
const teacherInfo: [string, number] = ["zhangsan", 18];
// enum 枚举
enum Direction {
Up,
Down,
Left,
Right,
}
Interface
interface.ts
相关使用如下:
// 接口
interface publicPoint {
x: number;
y: number;
z: number;
}
interface Point extends publicPoint {
a?: number;
}
interface Point1 extends publicPoint, Point2 {
a?: string;
b: string | number;
}
interface Point2 {
d: number;
}
const myPoint: Point = {
x: 1,
y: 2,
z: 3,
};
const myPoint1: Point1 = {
b: "123",
d: 4,
x: 1,
y: 2,
z: 3,
};
// 函数定义
interface Func {
(num1: number, num2: number): number;
}
const addFunc: Func = (arg1, arg2) => arg1 + arg2;
// 索引类型
interface Role {
[id: number]: string;
}
const role: Role = ["admin", "user", "guest"];
// console.log(role.length); // 当定义了索引类型,数组的length方法将不存在,包括Array原型链上的其他方法也不存在
const role1: Role = {
0: "admin",
1: "user",
2: "guest",
};
// 绕开多余的属性检查
interface MyType {
color: string;
[prop: string]: any; // 索引签名 这里的 prop 可以是任意类型
}
const getTypes = (myType: MyType) => {
return `${myType.color}`;
};
// 类型断言
getTypes({
color: "red",
type: "color",
} as MyType);
// 索引签名
getTypes({
color: "red",
type: "color",
num: 0,
a: () => {},
});
Class 类
ts-class.ts
相关使用如下:
class Person {
// public - 公共的,允许在类的外面进行调用
// protected - 受保护的,只允许在类的内部和子类中进行调用
// private - 私有的,只允许在类的内部进行调用
private name = "zahuopu";
protected name1 = "zahuopu1"; // 被保护的
getName() {
return this.name + this.name1;
}
}
const person = new Person();
console.log(person.getName()); // zahuopu
class Person1 extends Person {
constructor() {
super();
console.log(super.getName()); // zahuopu
console.log(this.getName()); // zahuopu1
}
getName() {
return "zahuopu1";
}
}
const person1 = new Person1();
console.log(person1.getName()); // zahuopu1
// 类类型接口
interface FoodInterface {
type: string;
}
class FoodClass implements FoodInterface {
constructor(public type: string) {}
}
// class FoodClass2 implements FoodInterface {
// type: string;
// constructor(args: string) {
// this.type = args;
// }
// }
// 接口继承类
// 1.接口可以继承类,当接口继承了类之后,会继承成员(类型),但是不包括实现;
// 2.接口还会继承private和protected修饰的成员,但是这个接口只可被这个类或它的子类实现
interface I extends Person {}
// 类与类,接口与接口之间使用 extends
// 类与接口之间使用 implements
class C extends Person implements I {
getName() {
return this.name1 + "new Class C";
}
}
const instance = new C();
console.log(instance.getName()); // zahuopu1new Class C
范型
generic.ts
在定义函数、接口或类的时候不预先制定数据类型,而在使用时再指定类型的特性。
相关使用如下:
const pushArr = <T>(arr: T[], item: T): T[] => {
arr.push(item);
return arr;
};
const arrnum: number[] = [1, 2, 3];
pushArr<number>(arrnum, 3);
pushArr<string>(["1", "2"], "3");
// 交换范型
function swapGeneric<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]];
}
const result = swapGeneric(["zahuopu", 2025]);
console.log(result); // [ 2025, 'zahuopu' ]
TS中的声明
声明:在文件中定义好函数、接口或类的类型;
声明文件:把声明语句放到一个单独的文件;
PS:声明文件必须以 .d.ts
为后缀。
如何生成声明文件?
打开 tsconfig.json
文件,放开两个配置
"declaration": true,
"outDir": "./dist",
在终端我们运行 npx tsc
命令,我们就可以得到 dist 文件夹了,至此声明文件完成生成。
总结
本篇文章,我们学习了TS的一些基本使用并认识了如何生成声明文件。实践出真知,后续我们还会在项目中使用TS,在真实场景中锻炼对TS的熟练度。
好啦,本篇文章到这里就要和大家说再见啦,祝你这篇文章阅读愉快,你下篇文章的阅读愉快留着我下篇文章再祝!
参考资料:
- TS · 百度百科
- NestJS 从入门到实战