ts基础
约 3111 字大约 10 分钟
2025-05-02
Type + JavaScript JavaScript 的超集(js有的ts都有)
增加了类型支持

2. ts相对js优势

3. ts包安装
命令
npm i -g typescript
tsc -v 查看版本
1. ts 转换为js
命令
tsc hello.js

运行ts代码
创建ts文件 ---> 编译(tsc 文件名.ts) --> 运行(node 文件名.js)
2. 简化Ts运行步骤
安装 ts-node包
命令
npm i -g ts-node
运行
ts-node 文件名.ts
添加tsconfig.json
{
"ts-node": {
"compilerOptions": {
"module": "CommonJS"
}
}
}
4. ts常用类型
1. 类型注解
: 类型 // 约定变量是什么类型 ,不可赋值其他类型
: number
2. 类型别名
同一类型 重复使用
type 类型别名 = 类型
type numStrArr = (number | string)[]
let arr: numberStrArr = [1, '2']
3. 类型注解使用
原始类型
let num: number = 18 let str: string = '张三' let isLoading: boolean = false let a: null = null let b: undefinde = undefinde let s: symbol = symbol() let a: null = null let b: undefinde = undefinde let s: symbol = symbol()
数组类型
let numbers: number[] = [1, 3, 5] let numbers: string[] = ['a', 'b'] let strings: Array<string> = ['a', 'b'] // 不推荐 // 既要number 又要string的数组 // 联合类型 let arr: (number | string)[] = [1, 'a'] let arr3: number | string[] = 1
函数类型
- 单独添加参数和返回值
const add = (num1: number, num2: number): number => { return num1 + num2 //必须要有返回值 }
- 统一指定参数类型 返回值类型 必须是表达式函数
const add: (num1: number, num2: number) => number = (num1, num2) => { return num1 + num2 }
- 没有返回值
const greet = (name: string): void => { console.log(name) }
- 可传可不穿【可选参数后不可以有必选参数】
const add3 = (num1?: number, num2?: number): void => { console.log(num1) console.log(num2) } // add3(1, 2) add3(1)
对象类型 【注意使用分号隔开】
let obj: {name: string; age: number; add(num1: number, num2: number): number} = {
name: '张三',
age: 15,
add(num1, num2) {
return num1 + num2
}
}
let obj1: {
name: string
age: number
add(num1: number, num2: bunber): numbers
} =
{
name: '张三',
age: 18,
add(num1, num2){
return: num1 + num2
}
}
对象数组类型
interface User{ name:string, age:number } let list:(User)[] = [{name:"黄四郎",age:45},{name:"马邦德",age:44}]
4. 接口
为了实现对象类型的复用
interface 类型名 {具体属性类名}
interface Iperson {
namme: string
age: number
add(): void
}
1. 接口与类型别名的区别
相同点:都可以为对象定义重复类型
不同点:接口只可以为对象定义重复类名
类型别名既可以为对象也可以给其他对象定义
type Iperson = { name: string age: numbert add(): void } let obj: Iperson = { name: '张三', age: 12, add() { } }
2. 接口继承
如果两个接口有相同的属性类型,可以通过extends关键字继承 继承接口就有了被继承的全部类型属性
interface Point2D {x: number; y: number} interface Point3D extends Point2D {z: number}
5. 元组
可以为数组限制数组的元素个数
let arr: [number, number] = [112.3, 13.2] // 只可以有2个元素
6. 类型推论
可以省略注解的书写
使用场景
- 在变量初始的时候赋予初始值
let num = 12 // let num: number = 12
- 在函数参数指定类型后返回值注解可以不写
const add = (num1: number, num2: number) =>{ return num1 + num2 // 返回值为number }
7. 类型断言
在获取dom节点时,类型是 Element 此次只可以获取标签的公共属性
需要利用as 限制具体类型
const a = document.querySelector('.a') as HTMLAnchorElement
可以利用 console.dir(节点) 查看类型
8. 字面量类型
就是为变量固定某一个值,和const一样
const str = 'abc' // 类型就是为 'abc' 只可以为 'abc'
let num: 18 = 18 // 这个值只可以为18
使用场景
在一个函数里面只可以传入固定值
const chang = (str: 'up' | 'left') => { // 参数只可以传入 'up' 'left' }
9. 枚举类型【还有值】
利用关键字 enum
枚举类型 = 字面量 + | // 定义多个字面量类型
enum 枚举名称 {具体的字面量类型} // 不只是类型 还有值
enum Direction {Up, Down, Left, Right}
访问枚举成员
enum Direction {Up, Down, Left, Right} Direction.Up // 返回的是索引 默认值为0 Direction[0] / Up 访问值 enum Direction {Up, Down, Left, Right} 0 1 2 3 enum Direction {Up = 1, Down, Left, Right} 1 2 3 4
举例
enum Direction {Up, Down, Left, Right} cont change = (direction: Direction) => { console.log(direction) // 0 索引 } change(Direction.Up)
enum Response1 { Success = "SUCCESS", Failure = "FAILURE" } console.log(Response.Success); // 输出 "SUCCESS" [3,4](@ref)
数字枚举
enum Direction {Up = 1, Down, Left, Right} // 后面自动增加 1 2 3 4 enum Direction {Up = 1, Down = 2, Left = 15, Right = 4} 1 2 15 4
字符串枚举注意点
enum Response1 { Success = "SUCCESS", Failure // 错误写法 // 第一个赋值字符串后 第二个必须赋值 } console.log(Response.Success); // 输出 "SUCCESS" [3,4](@ref)
10. any类型【不推荐使用】
any 是TypeScript的逃生舱 让ts的安全机制失效
默认的any类型 初始变量不负责, 函数参数不限定类型 所有这种情况时要注意添加类型
let num: any = 12
num = 'a' // 不报错
a() //不报错
11. typeof 的使用
可以根据上下文有点变量或属性(不可是函数调用类型) 来再用次类型 减少相同类型的多次书写
let user = {name: '张三', age: 13}
let obj: typeof user // 此时obj 就是{name: string, age: number} 类型
12. 类的基本定义[类也可使类型]
- 类的基本定义
class Person {
// public 表示实例公共属性
public name: string;
public age: number;
// public可以省略
like: string;
constructor(name: string, age: number, like: string) {
this.name = name;
this.age = age;
this.like = like
}
// 实例方法
public say(): string {
return '你好啊,我是' + this.name;
}
// 静态方法
static eat(food: string): string {
return '我正在吃' + food;
}
}
let p1 = new Person('张三', 22, '抽烟,喝酒,烫头');
console.log(p1);
类的简写
class Person { // 省略写法,不需要提前定义类型 // public name: string; // public age: number; // like: string; constructor( public name: string, public age: number, public like: string) { // 省略写法,不需要再去对每个属性赋值 // this.name = name; // this.age = age; // this.like = like } // 实例方法 public say(): string { return '你好啊,我是' + this.name; } // 静态方法 static eat(food: string): string { return '我正在吃' + food; } }
类的继承
class Ren {
name: string;
constructor(name: string) {
this.name = name
}
move() {
console.log('移动')
}
}
class User extends Ren{
siHai() {
conole.log('你好')
}
}
let user = new User()
user.move() // 可以访问父类的方法
类的实现
interface Singable { sing(): void {} } class Person implements Singable { sing() { console.log('唱歌') } }
1. 类的修饰符
类的属性和方法 有特定的作用或者限制 就需要通过修饰符进行处理
js中类的修饰符: public static readonly(只读)
ts中类的修饰符:除了js类的三个修饰符之外,新增了:
- public (公共) 公共属性、方法,可以在实例以及子类中访问
- protected (保护) 只能在子类中访问该属性和方法
- private(私有) 只能在当前类中访问该属性和方法
- readonly(只读属性可以初始化)【只可以修饰属性】 防止构造函数外对变量的赋值
class Person {
protected age!: number;
private name!: string;
public sex!: string;
private getName() {}
protected getAge() {}
public getSex() {}
// name 和 getName() 只能在 Person 中用 this 访问
}
class User extends Person {
constructor() {
super();
// User中可以访问 getAge() 和 age 以及被 public 修饰的属性以及方法
}
}
const person = new Person(); // person 只能访问到 getSex() 和 sex
注意: private 私有属性与方法 只能在当前类中使用,不能通过子类 和 this实例访问
class Person{
private name:string;
constructor(name:string){
this.name = name;
}
private say(){
return 'ssss';
}
// 私有方法只能通过当前类进行使用
public xxx(){
console.log(this.name);
console.log(this.say())
}
}
let p1 = new Person('张麻子');
// p1.name = '黄四郎' // 私有属性 使用报错
// p1.say() //私有方法调用报错
p1.xxx() //通过实例正确的使用方法
console.log(p1); //Person { name: '张麻子' }
13. 类型兼容性
ts采用的是结构化类型系统
如果两个对象具有相同的形状,则认为他们是同一类型
class Point {x: number; y: number}
class Point2 {x: number; y: sumber}
const p: Point = new Point2() // 不会报错
1. 对象类型的兼容
成员变量多的类型可以赋值给成员少的类型
interface A { x: number; }
interface B { x: number; y: string; }
let a: A = { x: 1 };
let b: B = { x: 1, y: "2" };
a = b; // 允许(B 的成员包含 A 的所有成员)[1,4](@ref)
// b = a; // 报错,缺少属性 y
2. 函数之间的兼容性
1. 参数数量函数
参数少的函数可以赋值给参数多的函数
type F1 = (a: number) => void;
type F2 = (a: number, b: string) => void;
let f1: F1 = (a) => {};
let f2: F2 = f1; // 允许(F1 参数更少)[1,3,4](@ref)
2. 父兼容子的参数[逆变]
父类型参数可以接受子类型参数
interface Parent { name: string; }
interface Child extends Parent { age: number; }
type FParent = (p: Parent) => void;
type FChild = (c: Child) => void;
let fChild: FChild = (c) => {};
let fParent: FParent = fChild; // 允许(参数逆变)[5](@ref)
3. 函数返回值类型
原始类型只要类型相同就可以赋值
对象类型 满足返回最多的 可以赋值给返回值少的
// 原始类型
type F1 = () => string
type F2 = () => string
let f11: F1
let f22: F2
f11 = f22
f22 = f11
//对象类型
type F1 = () => {x: number}
type F2 = () => {x: numbe; y: number}
let f11: F1
let f22: F2
f11 = f22 // 多给少
14. 交叉类型
类似于类的接口继承,用于组合对公类型为 一个类型 &
interface Person {name: string}
interface Contact {age: number}
type Per = Person & Contact
let obj: Per = {
name: '张三',
age: 18
}
1. 交叉类型与接口继承的区别

15. 泛型
- 泛型写法
function fn<T>(a:T):T{
return a;
}
fn(100) //100
fn('张麻子') //张麻子
fn(true) //true
//调用时传入泛型的类型
fn<number>(1000) //1000
fn<object>({name:'张麻子'}) //{name:'张麻子'}
简写方式
多个泛型参数
function fn<N,M>(a:N,b:M):N{
return a;
}
console.log( fn(1000,'sss') ); //1000
- 泛型 约束
使用泛型之后 会造成一些问题: 泛型之间不能使用运算符,泛型拿到数组、元祖之后没有length
解决length问题需要使用到 泛型约束
泛型约束:可以理解为 该泛型可以包含的属性及属性类型
这里出现
extends
关键字,此处表示泛型必须包含某种类型,从而在调用时约束了传入的类型。
function fn<T>(arr:T):number{
return arr.length; //报错 泛型T 不存在 length属性
}
console.log( fn([100,200,300]) );
解决办法
function fn<T>(arr: T[]): T[] {
console.log(arr.length) // 2
}
fn([1,2])
// 定义泛型的约束
interface Len{
length:number
}
function fn<T extends Len>(arr:T):number{ // extends Len T必须要有length属性 这样T类型的arr就可以访问length属性了
return arr.length;
}
console.log( fn([100,200,300])); //3
- 多个泛型参数
function fn<N,M>(a:N,b:M):N{
return a;
}
console.log( fn(1000,'sss') ); //1000
案例:创建一个函数来获取对象有的属性值
function getValue<T, k extends keyof T>(obj: T, key: K) { // keyof 生成对象属性的类型 'name' | 'age'
console.log(obj[key])
}
getValue({name: '张三',age: 14}, name) // 这样就限制了第二个参数必须传对象有的属性
泛型接口
泛型问题
泛型之间不能使用运算符
解决方案: 函数重载
function add<T>(a:T,b:T):T{
return a+b //报错 两个泛型不能进行加法运算
}
- 函数重载
需要注意的是只有最后一个才是真正的函数,其他的地方只能是函数类型的定义。
function add(a: string, b: string): string
function add(a: number, b: number): number
function add(a: any, b: any) {
return a + b;
}
console.log(add(11,22)); //33
console.log(add('ssss','eeeee')); //sssseeeee
泛型工具
Partial 变为可选属性
Readonly 变为只读
Pick<Type, key> 获取其中一部分

Record<Keys, Type> 构造对象类型
16. never 不存在的类型
抛出异常,或者永远不会有返回值的函数以及永远不会为真的类型返回
never
。
function infiniteLoop(): never {
while (true) {}
}
function error(): never {
throw '异常错误';
}
error()
infiniteLoop()
17. unknown 未知类型
unknown 和 any 很类似
定义为 unknown 类型的变量可以接收 任意数据类型
unknown 的变量只能赋值给 unknown 和any 类型的变量
any 定义的类型变量可以赋值给任意类型变量
let a:unknown;
a=1;
a='222'
console.log(a); //'222'
let a:unknown = '100';
// let b:string = a; //不能讲unknown 类型 分配给string类型
let c:unknown = a; //'100'
let d:any = a; //'100'
18. 索引签名类型

19. 映射类型
