typescript学习笔记(全)
1.安装
全局安装
npm i -g typescript
局部安装
npm i typescript
初始化
tsc --init
就会在所在目录下创建出一个tsconfig.json的ts配置文件
2.编译
如果是全局安装
tsc index.ts
就会在同目录下编译出一个index.js文件
如果是局部安装
npx tsc index.ts
3.特性
1.静态类型:
编译时会检查变量和类型是否匹配,如果不匹配,编译不会通过
比如
let name:string = '王惊涛'
可以编译通过
let name:number = '王惊涛'
就会编译报错
2.类型推断:
ts会根据值进行类型推断
let name = '王惊涛'
ts编译器就会自动判断这个类型为string
下面的操作,就属于错误操作
let name = '王惊涛'
name = true
3.接口:
通过interface关键字定义接口,例如
interface interface_test_1{name:stringage:numberlove:Function
}
let interface_test_1:interface_test_1 ={ name:'wjt',age:29,love:()=>'game',
}
4.类型别名:
使用type关键字可以定义类型别名,可以定义多个类型,方便重复使用
type result_type = string | boolean
let result1:result_type = '成功'
let result2:result_type = false
5.枚举:
使用enum关键字命令一组常量,提高代码可读性
enum Direction {Up = "UP",Down = "DOWN",Left = "LEFT",Right = "RIGHT"
}let dir: Direction = Direction.Left;
console.log(dir); // 输出: "LEFT"
6.元组:
元组用于定义固定数量和类型的数组。比如2d坐标,固定是两个数字值,代表x和y
let position:[number,number] = [1,1]
7.访问修饰符
在class类中定义了public(公共),private(私有),protected(受保护)修饰符,用于控制属性或方法的可见性,支持更好的封装
class Person {private name: string;protected age: number;public constructor(name: string, age: number) {this.name = name;this.age = age;}
}
8.抽象类
使用abstract定义抽象类,抽象类不能直接实例化,需要由子类进行实例化
abstract class Game {abstract desc(): void; // 抽象方法
}class Moba extends Game { // 继承desc() {console.log('moba类型是推塔游戏');}
}let Lol = new Moba(); // 实例化英雄联盟
Lol.desc(); // 调用 desc 方法
9.泛型:
泛型是参数化类型,定义一个类型参数,代表某种固定类型。如下的示例中,T就代表了传入的number
function addNum<T>(value: T): T {return value+1;
}let num = addNum<number>(1);
console.log(num) //2
10.命名空间:
ts中的导入与导出和ES6模块系统一样,并且还有Namespace命名空间
utils.ts中导出函数
export function addNum(a:number,b:number):number{return a+b
}
app.ts
import {addNum} from './utils.ts'
addNum(1,2)
11.类型守卫:
使用typeof检查类型
function resultFilter(result:string | boolean){if(typeof result === 'string'){console.log('字符串类型)}else{console.log('布尔类型')}
}
12.可选链和空值合并运算符
可选链?.和空值合并运算符??都可以做到代码中应对undfined和null值的处理
let user = { name: "王惊涛", address: { city: "北京" } };
console.log(user?.address?.city); // 如果 address 存在则输出 city,否则返回 undefinedlet value = null;
console.log(value ?? "default"); // 如果 value 为 null 或 undefined,则返回 "default"
13.类型兼容器和工具类型
TypeScript 提供了一些工具类型,如 Partial
、Pick
、Readonly
、Record
等,这些类型可以帮助生成新的类型,简化类型定义。
interface Person {name: string;age: number;love: string
}let wjt: Partial<Person> = { name:'王惊涛',age:29 }; // 可选属性
4.ts基础类型
归纳
类型 | 描述 | 示例 |
---|---|---|
string | 文本 | let name:string = ‘王惊涛’ |
number | 数字类型 | let age:number = 29 let num:number = 2.8 |
boolean | 布尔值 | let gender:boolean = true |
array | 相同类型的元素数组 | let arr:string[] = [‘王惊涛’,‘小马’] |
tuple | 元组,已知类型和固定长度 | let position:[string,number,number] = [‘北京’,1,1] |
enum | 命名常量 | enum Game{LOL, CF, DNF } let loveGame:Game = Game.LOL |
any | 任意类型,不限制 | let result:any = true result = ‘王惊涛’ |
void | 无返回值(一般用于函数) | function play():viod{ console.log(‘打联盟’) } |
null | 空值 | let empty:null = null |
undefined | 未定义 | let value:undefined = undefined |
never | 不会有返回值 | function error():never { throw new Error(‘error’) } |
object | 非原始类型 | let wjt:object = {name:‘王惊涛’,age:29} |
union | 联合类型 | let result:string I number = ‘success’ |
unknow | 不确定类型 | let value:unknow = ‘王惊涛’ |
null 和 undefined 是所有类型的子类型
布尔类型
//布尔值
let bool_1:boolean = false
console.log(bool_1,'bool_1')
数字类型
//数字
let num_1:number = 6 //十进制
let num_2:number = 0xf00d //十六进制
let num_3:number = 0b1010 //二进制
let num_4:number = 0o744 //八进制
console.log(num_1,num_2,num_3,num_4)
字符串
//字符串
let str_1:string = '字符串'
let str_2:string = `模板字符串`
console.log(str_1,str_2)
数组
let arr_1 : number[] = [1,2,3]
let arr_2 : Array<number> = [2,3,4]
let arr_3 : string[] = ['a','b','c']
let arr_4 : Array<string> = ['b','c','d']
console.log(arr_1,'arr_1')
console.log(arr_2,'arr_2')
console.log(arr_3,'arr_3')
console.log(arr_4,'arr_4')
元组Tuple
let tuple_1:[string,number,boolean] = ['a',1,true]
// tuple_1 = [1,'a',false] //error
tuple_1 = ['b',2,false]
console.log(tuple_1,'tuple_1')
枚举
enum Color{Red="red",Green=2,Blue=3}
let c_1 : Color = Color.Green
console.log(c_1,'c_1')
let colorName : string = Color[2]
console.log(colorName,'colorName')
任意类型
let any_val1 : any = '任意值'
let any_val2 : any = ['1',2,3]
any_val1 = {name:'any_obj'}
any_val2 = null
console.log(any_val1,any_val2)
Void类型
function fn_1():void{console.log('I`m a funciton')
}
let void_val1:void = null
void_val1 = undefined
// void_val1 = '字符串' //error
null和undefined类型
let null_1 : null = null
let undefined_1: undefined = undefined
// null_1 = '哈哈哈' //error
Never类型
function errorFn_1():never{throw new Error('哈哈哈')// return '哈哈哈' error
}
function neverFn_1():never{while (true){}
}
object类型
declare function create(obj:object | null) :void
create({val:111})
create(null)
// create(number) //error
//数组
let arr_1 : number[] = [1,2,3]
let arr_2 : Array<number> = [2,3,4]
let arr_3 : string[] = ['a','b','c']
let arr_4 : Array<string> = ['b','c','d']
console.log(arr_1,'arr_1')
console.log(arr_2,'arr_2')
console.log(arr_3,'arr_3')
console.log(arr_4,'arr_4')//元组Tuple
let tuple_1:[string,number,boolean] = ['a',1,true]
// tuple_1 = [1,'a',false] //error
tuple_1 = ['b',2,false]
console.log(tuple_1,'tuple_1')//枚举
enum Color{Red="red",Green=2,Blue=3}
let c_1 : Color = Color.Green
console.log(c_1,'c_1')
let colorName : string = Color[2]
console.log(colorName,'colorName')//任意类型
let any_val1 : any = '任意值'
let any_val2 : any = ['1',2,3]
any_val1 = {name:'any_obj'}
any_val2 = null
console.log(any_val1,any_val2)//Void类型
function fn_1():void{console.log('I`m a funciton')
}
let void_val1:void = null
void_val1 = undefined
// void_val1 = '字符串' //error// null和undefined类型
let null_1 : null = null
let undefined_1: undefined = undefined
// null_1 = '哈哈哈' //error//Never类型
function errorFn_1():never{throw new Error('哈哈哈')// return '哈哈哈' error
}
function neverFn_1():never{while (true){}
}//object类型
//非原始类型
declare function create(obj:object | null) :void
create({val:111})
create(null)
// create(number) //error//类型断言
let val_dy : any = '要被断言类型的值'
// let length_1 : number = (<string>val_dy).length
let length_1 : number = (val_dy as string).length
let arr_dy :any[] = ['哈哈哈','呵呵呵',(()=>1+'2')()]
let val_2 : string = (<string>arr_dy[2])
5.函数
函数定义类型
// function(参数:类型):返回值类型{}
function fun_test_1(num1:number,num2:number):number{return num1+num2
}
console.log(fun_test_1(1,2),'fun_test_1调用')function fun_test_2(name:string,age:number):void{console.log(`我是${name},我今年${age}岁`)
}
fun_test_2('wjt',28)
完整写法
// let 函数名:(参数:类型) => 返回值类型 = 函数体
let fun_test_3:(name:string,age:number) => object = function(name:string,age:number):object{return {name,age}
}
console.log(fun_test_3('wjt',29),'fun_test_3完整写法调用')
推断类型
let fun_test_4 = (num:number,str:string)=>{return num+str
}
console.log(fun_test_4(56,'个民族'),'自动推导返回类型')
可选参数
ts中形参必须对应有实参,如果用?,可以让该参数变为可选参数,默认是undefined
// function fun_test_5(name:string,age:number){
// console.log(name,age)
// }
// fun_test_5('wjt') //errorfunction fun_test_5(name:string,age?:number){console.log(name,age,'fun_test_5函数调用')
}
fun_test_5('wjt')
默认参数
function fun_test_6(name:string,age = 28){console.log(name,age,'fun_test_6函数调用')
}
fun_test_6('wjt')
剩余参数
function fun_test_7(firstParam:string,...otherParam:any[]){console.log(firstParam,'第一个参数')console.log(otherParam,'其余参数')
}
fun_test_7('wjt',28,()=>'game',{love:'study'})
6.interface(接口)
基础使用
interface interface_test_1{name:stringage:numberlove:Function
}
let interface_test_1:interface_test_1 ={ //属性多了对不上name:'wjt',age:29,love:()=>'game',// work:'coder' //error
}// let interface_test_2:interface_test ={ //error 属性少了对不上
// name:'mashi',
// }
console.log(interface_test_1,'interface_test_1')
可选属性
interface interface_test_2{name:stringwork?:boolean //写不写都行price:number
}
let wjt_1:interface_test_2 = {name:'wjt',work:true,price:24000
}
let mashi_1:interface_test_2 ={name:'mashi',price:10000
}
console.log(wjt_1,'wjt_1')
console.log(mashi_1,'mashi_1')interface person_2{
name?:string
age?:number
}let person_2:object = {name:'wjt',age:'28'} //这里age字符串也没有报错
let getWife =(person_2:person_2):{name:string,age:number}=>{let wife:person_1= {name:'null',age:0,love:'wjt'}if(person_2.name){wife.name = 'mashi'}if(person_2.age){wife.age = 29 }return wife
}
console.log(getWife(person_2))
任意属性名和任意属性值
interface interface_test_3{name:string,age?:number,[propName:string]:any //任意属性名和任意属性值
}
let interface_test_3:interface_test_3= {name:'wjt',work:'coder',love:()=>'game'
}
函数接口
interface interface_fun_1{(obj:object):object
}
interface fun_obj_1{name:stringage:numberwork:string// [propName:string]:any
}
let fun_obj_1:fun_obj_1 = {name:'wjt',age:28,work:'js-coder'
} let interface_fun_1:interface_fun_1 = (obj)=>{return Object.assign({val:1},obj)
}
interface_fun_1(fun_obj_1)
数组接口
interface interface_obj_arr_1{[index:number]:objectlength:number
}
let obj_arr_1 :interface_obj_arr_1 = [{name:'wjt'},{name:'xm'}
]
console.log(obj_arr_1,'obj_arr_1')
类接口
interface interface_class_1{class_fun_1:Functionclass_var_1:stringclass_var_2:number
}
class Class_1 implements interface_class_1{constructor(){}class_fun_1 : ()=>{}class_var_1:'字符串'class_var_2:0}
let class_shili_1 = new Class_1()
console.log(class_shili_1,'class_shili_1')
继承接口
interface extends_1{name:string
}
interface extends_2 extends extends_1{age:number
}
interface extends_3 extends extends_1,extends_2{love:Function
}
let extends_var_1 : extends_1 = {name:'wjt'}
let extends_var_2 : extends_2 = {name:'wjt',age:28}
let extends_var_3 : extends_3 = {name:'wjt',age:28,love:()=>'game'}
混合类型(函数对象)
interface interface_mix_1{(start:number):stringperson_name:stringage:numberlove:Function
}
function interface_mix_fun():interface_mix_1{let obj_fun = <interface_mix_1>function(start:number){console.log(start,'传入了值')}obj_fun.person_name = 'wjt'obj_fun.age = 28obj_fun.love = ()=>{console.log('打游戏')}return obj_fun
}
let obj_fun_1 = interface_mix_fun()
obj_fun_1(1)
console.log(obj_fun_1,'函数对象')
console.log(obj_fun_1.person_name,'函数对象名字')
console.log(obj_fun_1.age,'函数对象年龄')
console.log(obj_fun_1.love,'函数对象调用love方法')
接口继承类
class Class_2{name:string
}
interface interfaceAndClass extends Class_2{age:number
}
let info:interfaceAndClass = {name:'wjt',age:28}
console.log(info,'info')
7.class(类)
修饰符public
public代表默认公开,可以在任何地方被访问
class Class_1{public person_name:stringpublic constructor(name:string){this.person_name = name}public love(val){console.log(`我喜欢${val}`)}
}
let class_var_1 = new Class_1('wjt1')
console.log(class_var_1,'class_var_1')
console.log(class_var_1.person_name,'class_var_1的person_name名称')
修饰符private
private代表变量私有,只能被其定义的类所访问
class Class_2{private person_name:stringconstructor(name:string){this.person_name = name}
}
let class_var_2 = new Class_2('wjt2')
console.log(class_var_2,'class_var_2')
// console.log(class_var_2.person_name) //error
修饰符protected
protected代表受保护,只可以被自身和子类所访问
class Class_3{protected person_name:stringconstructor(name:string){this.person_name = name}
}
class Class_4 extends Class_3{private self_var:stringconstructor(name:string,self_var:string){super(name)this.self_var = self_var}public love(val){return '我喜欢'+val}
}
let class_var_4 = new Class_4('wjt4','自定义数据')
console.log(class_var_4,'class_var_4')
// console.log(class_var_4.person_name) error
// console.log(class_var_4.self_var) error
console.log(class_var_4.love('打游戏'))
readonly只读
class Class_5{readonly person_name:stringage:numberconstructor(name:string,age:number){this.person_name = namethis.age = age}
}
let class_var_5 = new Class_5('wjt5',28)
console.log(class_var_5,'class_var_5')
class_var_5.age = 29
// class_var_5.person_name = 'wjt' //error
类当接口使用
把类当interface一样去使用
class Class_10{person_name:stringage:number
}interface interfaceWithClass extends Class_10{love:Function
}let person_wjt:interfaceWithClass = {person_name:'wjt',age:28,love:()=>'game'}
console.log(person_wjt,'person_wjt')
8.泛型
允许在定义函数、类、接口等时使用占位符来表示类型,而不是具体的类型。
基础用法:泛型函数
function genericity_fun1<T>(name:T):T{return name
}
调用
// 写法1
let result_1 = genericity_fun1<string>('wjt')
//写法2:自动推导类型
let result_2 = genericity_fun1('wjt')
约定俗称的一些标识符
T 一般代表Type(类型)
function fun<T>(arg: T): T {return arg;
}
K ,V一般代表Key(键)和Value(值)
interface KeyValueObj<K, V> {key: K;value: V;
}
E 一般标识数组元素的泛型类型参数
function numArr<E>(arr: E[]): void {arr.forEach(item => console.log(item));
}
R 一般代表函数返回值的泛型类型参数
function hasResultFun<R>(value: R): R {return value;
}
泛型接口
// 基本语法
interface Person<T, U> {name: T;age: U;
}// 使用泛型接口
let wjt: Person<string, number> = { name: "王惊涛", second: 29 };
console.log(wjt);
泛型类
class Genericity_Class<T>{initVal:TaddFun:(x:T,y:T) => T
}//传入数字类型
let number_result_1 = new Genericity_Class<number>()
number_result_1.initVal = 0
number_result_1.addFun = function(x,y){return x+y}
console.log(number_result_1.addFun(1,2),'number_result_1.addFun')//传入字符串类型
let string_result_1 = new Genericity_Class<string>()
string_result_1.initVal = '初始化字符'
string_result_1.addFun = function(x,y){return x+y}
console.log(string_result_1.addFun('我是','字符串'))
泛型约束
使用T extends interfaceXXX进行约束
interface genericity_constraint1{length:number
}
function genericity_constraint2<T extends genericity_constraint1>(arr:T):T{console.log(arr.length,'genericity_constraint2的length')return arr
}
genericity_constraint2(['wjt','mashi'])
泛型默认值
function defaultValue<T = string>(arg: T): T {return arg;
}// 使用带默认值的泛型函数
let result1 = defaultValue("王惊涛"); // 推断为 string 类型
let result2 = defaultValue(29); // 推断为 number 类型
9.联合类型与交叉类型
联合类型
使用|连接两种类型: 类型1 | 类型2,该变量可设置为这两种类型
let age:number | string = '29'
age = 29
函数参数也可以这样设置
const getAge = (age:number | string): number | string=>{return age
}
数组也是可以的
let arr:number[]|string[] = [1,2,3]
arr = ['1','2','3']
交叉类型
使用&连接两种类型,可以将这两种类型合并
//交叉类型
interface prop1{name:stringage:number
}
interface prop2{love:()=>string
}const function2 = (personInfo:prop1 & prop2)=>{console.log(personInfo)
}
function2({name:'wjt',age:29,love:()=>'jscoder'})
10.类型推导与类型断言
类型推导
//默认推导为number类型
let age = 18//默认推导为字符串类型
let name = '王惊涛'//默认推导为布尔类型
let gander = true//函数返回值类型推导
function desc(name:string,age:number){return `我是${name},今年${age}岁` //返回值推断为字符串
}
let wjtDesc = desc(name,age) //类型为字符串
类型断言
当编辑器无法断定一个变量的类型,但是开发者知道,就可以手动指定一个变量的类型,有两种写法
let name = '王惊涛';// 写法1: 尖括号语法: <类型>变量 (不推荐)
let nameLength1: number = (<string>name).length;// 写法2: as语法: 变量 as 类型 (推荐)
let nameLength2: number = (name as string).length;// 定义接口
interface Person {name: string;age: number;
}// 动态类型
let wjt: any = { name, age: 29 };// 开发者可以断言 wjt 类型为 Person 类型,wjt_copy 也就是 Person 类型
let wjt_copy: Person = wjt as Person;
对比
特性 | 类型推导 | 类型断言 |
---|---|---|
触发方式 | 由编译器自动推断 | 由开发者手动指定 |
使用场景 | 编译器可以准确推断类型时 | 编译器无法推断类型或需要覆盖推断时 |
安全性 | 类型安全,编译器会验证 | 存在风险,开发者需确保断言类型正确 |
语法 | 无需显式语法 | 使用 <Type> 或 as Type |
11.类型别名
type可以定义类型别名,功能还是很强大的
基础类型
不过这个意义一般不大
type stringType = string
let name:stringType = '王惊涛'
联合类型
设置了固定的值,这个变量的值智只能从设置的值里拿,如果赋值一个没有设置的值,会报错
type genderType = "男" | "女"
let gender:genderType = "太监" //error,不好意思,大清之后无太监
对象类型
type Person = {name:stringage:numbergender:boolean
}let wjt:Person = {name:'王惊涛',age:29,gender:true}
函数类型
type addNumType = (x:number,y:number) => numberlet addNum :addNumType = (x,y)=>x+y
let num = addNum(1,1)
元组类型
type Position = [number,number]
let position:Position = [1,1]
type和interface的区别
虽然都可以实现类型定义
type Person1{name:stringage:numberhas:{xxx:stringyyy:string}
}interface Person2{name:stringage:numberhas:{xxx:stringyyy:string}
}
不过interface可以实现继承和扩展,而Type做不到
interface Man extends Person {nanFun:Function
}