一、TS核心语法+各种实战应用(上)
1.Typescript定义
融合了后端面向对象思想的超级版的JavaScript语言
1. TypeScript: 静态类型检查器
2. TypeScript为JS的超集 为强类型
3. JavaScript为弱类型
4. TS === JS + 类型 js有的ts都有
5. TS 规范了 JS类型声明 使之更加严谨
2.环境准备
npm init -y // 初始化一个package.json
yarn/npm/pnpm add typescript -D === --save-dev // 当前项目目录安装
yarn/npm/pnpm add typescript -g // 全局安装
tsc --init // 生成tsconfig配置文件
tsc demo.ts // 终端运行ts文件 // 将ts转为js浏览器可识别的代码
3.TypeScript的优势
优势一
编译时静态类型检测:函数或方法传参或变量赋值不匹配时,会出现编译借误提示,规避了开发期间的大早低级借误,省时,省力。
let str:string = "string" // 指定了string
str = 3 // error 只能赋值string类型的值
let arr:string[] = [] // 指定字符串数组类型
arr.forEach(()=>{})
let arr:string = '21' // 指定字符串
arr.forEach(()=>{}) // error 字符串是没有forEach方法的
优势二
: 自动提示更清晰明确
let cus = {
name: 'zhangsan',
degree: 'guardcard',
phone: '111'
}
interface ICus {
name: 'zhangsan',
degree: 'guardcard',
phone: '111'
}
cus/ICus 使用某个属性的时候会明确的提示 这个对象下有哪些属性
优势三
引入了泛型和一系列的 TS 特有的类型
优势四
强大的 d.ts
声明文件:声明文件像一个的目录一样,清晰直观展示了依赖库文件的接口,type类型
,类,函数,变量等声明.
优势五
轻松编译成JS文件: 即使TS文件有错误,绝大多数情况也能编译出JS文件
优势六
灵活性高: 尽管TS是一门强类型检查语言
,但也提供了any
类型 和 as any
断言,这提供了TS的灵活度
4.类型注解 与 类型推导
类型注解: 声明变量的时候就进行类型约束
let num:number = 3;
let str:string = '3';
let thruly:boolean = true;
let isNot:null = null;
let und:undefined = undefined;
类型推导: 通过右边变量的值推导出类型
let num = 30; // 就会自动推导出变量的类型
俩者之间的区别:
1.类型注解 约束类型之后不能更改为其他的类型
2.类型推导 根据自己写的值就会推导出对应的类型
5.Ts编译和编译优化
先打开tsconfig,json
"rootDir": "./src", // 输入目录
"outDir": "./dist", // 输出目录 用来存放src文件编译之后的文件目录
控制台执行tsc 将src文件编译到dist目录下
6.常用的24种TS类型
1.基本类型:
number
string
boolean
symbol
null
undefined
2.根类型:
其他类型的父类
Object: {} // 除了null,undefined 不能赋值给它,其他的都可以
Object === {} // {} 为 Object 的简写
3.对象类型
Array
function
object
4.枚举类型
4-1.枚举定义
enum(枚举)
用来存放一组固定的常量的序列
为什么要使用enum(枚举)?
解决多次if/switch 判断中值的语义化的问题
常量的局限性
1.方法参数不饿能定义为具体类型,只能初级使用 number, string 基本类型替代
2.降低了代码的可读性,可维护性
没有ts时候使用常量解决
enum(枚举)正好可以解决 使用常量带来局限性
const Status = {
MANAGER_ADUIT_FAIL: -1;
NO_ADUIT: 0,
MANAGER_ADUIT_SUCCESS: 1,
FINAL_ADUIT_SUCCESS: 2
}
class MyAduit {
getAduitStatus(status: number): void {
if(status === Status.NO_ADUIT) {
console.log('无审核');
}else if (status === MANAGER_ADUIT_SUCCESS) {
console.log('管理审核通过');
}else if (status === Status. FINAL_ADUIT_SUCCESS) {
console.log('老板审核通过');
}
}
}
4-2.字符串枚举
// 数字枚举
enum Week {
// Monday 初始值为1 后面的每一项在 Monday=1的基础上逐渐递增
Monday = 1,
Tuesday, // 2
Wensday, // 3
ThirsDay,// 4
Friday, // 5
Sarturday,// 6
Sunday // 7
}
// 取值方式
console.log(Week.Monday);
console.log(Week["Monday"]); // 由key 取值
console.log(Week[1]); // 由值取key
4-3.数字枚举
// 字符串枚举
enum Week1 {
Monday = "Monday",
Tuesday = "Tuesday",
Wensday = "Wensday",
ThirsDay = "ThirsDay",
Friday = "Friday",
Sarturday = "Sarturday",
Sunday = "Sunday"
}
console.log(Week1.Monday);
console.log(Week1["Monday"]); // key 取值
4.4enum(枚举)的好处
1.有默认值和可以自增值,节省编码时间
2.语义更清晰,可读性增强
3.因为枚举是一种值类型的数据类型,方法参数可以明确参数类型为枚举类型
5.其他特殊类型:
5-1.any
应用场景:
1. 自定义守卫
2. 需要进行 as any 类型断言的场景
5-2.unknown
应用场景:
1. 一般用作函数参数: 用来接受任意类型的变量实参,但在函数内部只用于再次传递或输出结果,不获取属性场景
const getData = (data: any) => {
console.log(data.name); // unknown 的时候 “data”的类型为“未知”
// any 时候正常的 .name
}
getData({ name: "张三", age: 23 })
getData([ 3, 4 ])
5-3.any和unknown的区别
相同点:
1. any和unknown 可以是任何类的父类,所以任何类型的变量都可以赋值给any类型类型或者unlnown类型的变量
不同点:
1.any也可以使任何类的子类, 但unknown不可以,所以any类型的变量都可以赋值给其他类型的变量
let data: any = ['321', '1']
let num: number = data
2.不能拿unknown类型的变量来获取任何属性和方法,但any类型的变量可以获取任意名称的属性和任意名称的方法
5-4.never
定义: 什么都没有的类型
使用never避免出现未来扩展的类型没有对应类型的实现,目的就是写出类型绝对安全的代码
type DataFlow = string | number;
const data = (dataFlow: DataFlow) => {
// 类型收窄 将原来string和number类型 收窄为 string类型
if (typeof dataFlow === "string"){
console.log("字符串类型:",dataFlow.length)
} else if (typeof dataFlow === "number") {
console.log("数值类型:",dataFlow.toFixed(2));
} else {
// else 区间 是预留出来 未来类型的空间
// 如果 DataFlow 还有一个boolean那么else区间的类型就是布尔否则就是 never
let data=dataFlow // never
}
}
data("123”);
data(314);
5-5.void
当涉及函数的返回值时,void
类型表示该函数不返回任何值。它类似于 JavaScript 中的没有明确返回值的函数,默认返回值为 undefined
。
在 TypeScript 中,可以通过在函数声明时将其返回类型设置为 void
,来表明这个函数不会返回任何实际值。这对于执行一些操作而不需要返回结果的函数非常有用。例如:
function Fun(text: string): void {
console.log(text);
}
在这里,Fun
函数将字符串文本作为参数,但它不返回任何值。它只是将文本打印到控制台,所以返回类型被设置为 void
。
当调用 Fun
函数时,它不会返回任何值,它只是执行其中的代码并打印消息
Fun("Hello, TypeScript!"); // 输出:Hello, TypeScript!
如果您有一个函数执行某些操作,但是不需要其结果,那么可以将其返回类型设置为 void
。
需要注意,void
类型只适用于函数的返回值,而不适用于变量。这是因为 TypeScript 的类型系统通常用来描述值的形状和用途,而不是变量的状态。
5-6.tuple
元祖可变元祖
暂未更新 在学习
6.合成类型
6-1.联合类型
let str: string | number = 3; // 或的关系 | 可以使string也可以使number
6-2.交叉类型
Type 可以定义任意一种数据类型
type Obj1 = { username: string }
type Obj2 = { age: number }
let obj1: Obj1 = { username: "abc"}
let obj2: Obj2 = { age: 23 }
// & 并集 合并
let obj3: Obj1 & Obj2 = { // obj3 {username: string, age: number}
username: "wangwu",
age:40
}
console.log(obj3);
7.字面量数据类型
type A = 'success' | 'error' | 0 | 1 | true | false // 应用的时候只能选择这几个值
// 示例
type Flag = 0 | 1 | 'success' | 'error' // 只能传入规定的字面量值
const isStart = (isFlag: Flag) => {
if (isFlag) {
console.log('open')
} else {
console.log('close')
}
}
isStart(1)
8.深入理解接口 + 真实应用场景
- 另一种定义对象类型的类型
- 接口应用场景
- 一些第三方包或者框架底层源码中有大量的接口类型
- 提供方法的对象类型的参数时使用
- 为多个同类别的类提供统一的方法和属性声明
8-1.如何定义接口
// 定义一个信息类型
interface InfoType {
name: string;
age: number;
gender: string;
sayHi(): void;
}
// 定义一个变量来使用它
const info: InfoType = {
name: 'John',
age: 36,
gender: 'Female',
sayHi() {
console.log('sayHi');
}
}
8-2.接口继承
// 动物类型 抽离动物共有的属性
interface Animal {
name: string;
age: number;
animalType: string;
sex: '公' | '母';
}
// DogType 继承了 Animal 的属性类型
interface DogType extends Animal {
guradHome(): void;
}
// test1 属性中必须包含DogType 与 Animal 合并之后的所有属性
// 除非带有可选属性 ? 来表示 如: animalType?: string;
const test1: DogType = {
guradHome() {},
name: '二狗',
age: 1,
animalType: 'run',
sex: '公'
}
8-3.为多个同类别的类提供统一的方法和属性声明
- 方便统一管理
interface List {
add(): void;
remove(): void;
}
class ArrayList implements List {
add(): void {
throw new Error("Method not implemented.");
}
remove(): void {
throw new Error("Method not implemented.");
}
}
class LinkedList implements List {
add(): void {
throw new Error("Method not implemented.");
}
remove(): void {
throw new Error("Method not implemented.");
}
}
8-4.可索引签名,及2个容易忽略的细节
// 可索引签名
interface Product {
name: string;
price: number;
account: number;
// [] 固定写法 x代表未知的属性名 && 为字符串类型
// 不明确的时候写成any 明确的时候直接写但是 要兼容上面的类型 可使用联合类型 string | number
[x: string]: any; // string | number 未知属性可索引签名
}
let p: Product={
name: "张三",
price: 1000,
account: 100,
// 符合 [x: string]: any; 类型的
// 以下这种情况都符合
description: "描述",
stock: 10000,
[Symbol("buy")]: 23,
1: "gold",
true: true,
}
8-5.索引访问类型,及深入扩展
// 索引访问类型
const symid = Symbol("productSc")
interface Product {
[symid]: number | string;
name: string;
price: number;
account: number;
buy(): void
}
// 接口重名可合并---重载
interface Product {
age: number,
}
type A = Product["buy"] // "" 中得到的是一个类型 Product也是类型
type B = Product["price"|"name"] // 联合类型
/**
* @description 获取symid 的类型该如何获取
*/
type S = Product[symid] // 错误 symid 因为本身就表示变量值
type S = Product[typeof symid] // typeof 可以获取js变量类型的操作符
/**
* @description 想要获取接口里面所有的属性名
*/
type Pkeys = keyof Product // === "name" | "price" | "account" | "buy" | typeof symid
let key: Pkeys="account"
// let key1: "name" | "price" | "account" | "buy" | typeof symid = "account"
// 使用泛型来获取
type AllKeys<T> = T extends any?T:never
type key2 = AllKeys<keyof Product>
9.null和undefined + 相关重要细节
9-1.javascript中
null
表示什么都没有,表示一个空对象引用
let obj = null
console.log(typeof null) // object
undefined
声明一个变量,但是没有赋值,该变量值为undefined
var a
console.log("a", a)
console.log(typeof undefined) // undefined
9-2.Typescript中
let str: string
console.log(str); // 没有赋值的情况下回报错
let str1: string | undefined = undefined; // 可以赋值undefined 也可以赋值字符串
console.log(str1); // 使用联合类型 是可以允许为空的
let str2: string = undefined; // 在ts中是不允许将undefined赋值给string类型
// 有一种方式可以解决当前报错
// 在tsconfig.json中 严格模式下strict 的 strictNullChecks
// 设置为false即可解决,但是不建议
// "strict": true,
// "strictNullChecks": true,
// undefined 应用
// 不加? 时候会报错(必须要有一个参数) ?表示参数可传可不传
const data = (dt?: string) => {
// 1. ! 非空断言 表示我确定这里面一定不等于空
dt!.toString();
// 2. if 判断
if(dt) dt.toString()
}
data()
// 可以接收undefined的三种类型 null 也是同理
let d1: unknown = undefined
let d2: any = undefined
let d3: undefined = undefined
// 可以接收null的三种类型
let c1: unknown = null
let c2: any = null
let c3: undefined = null
10.看似简单地取值为什么会抛出错误
let obj = { userName: '张三', age: 12 }
// 一个不固定的字符串做为固定对象obj属性名的索引是不可以的,使用const改为常量就可以了
let username = 'userName' // 错误
const username = 'userName' // 正确
let test = obj[username]
错误:
1.元素隐式具有 "any" 类型,因为类型为 "string" 的表达式不能用于索引类型
"{ userName: string; age: number; }"。
2.在类型 "{ userName: string; age: number; }" 上找不到具有类型为 "string"
的参数的索引签名
let obj:object = { userName: '张三', age: 12 }
const username = 'userName'
let test = obj[username] // objject上就不存在userName
错误:
元素隐式具有 "any" 类型,因为类型为 ""userName""的表达式不能用于索引类型 "{}"。
类型“{}”上不存在属性“userName”
11.interface 与 Type的区别?
语法差异
- interface 使用 interface 关键字定义
- type 使用 type 关键字定义
合并能力
- interface 接口可以重名 type不可以重名
- interface 同名接口会被合并为一个接口 type会产生冲突 发生报错565656565656
对象类型 vs 声明类型
- interface 用于定义对象类型,可以描述对象的
结构``属性
和方法
也可以实现继承(extends) - type 支持联合类型 '|', 交叉类型 '&'
12.TS函数和TS函数类型
// 1.
//函数返回值这里指定的是返回number,但是ts其实会根据你返回的会自动进行类型推导
function info(name: string, age: number): number {
console.log(name, '===name===')
console.log(age, '===age===')
return 4
}
info('122', 12)
// 2.
// 函数表达式类型写法 会根据右边函数推导并且返回给 变量info
const info = (name: string, age: number): number => {
console.log(name, '===name===')
console.log(age, '===age===')
return 4
}
// 3.
// 定义指定函数的类型 (比较麻烦)
const info: (name: string, age: number) => number =
(name, age) => {
console.log(name, '===name===')
console.log(age, '===age===')
return 4
}
// 使用type将类型抽离
type InfoFun = (name: string, age: number) => number
const info: InfoFun = (name, age) => {
console.log(name, '===name===')
console.log(age, '===age===')
return 4
}
// 关于reset参数
// reset这里给了any 根据实际情况还是要自己组装正确的数据类型 少用any
function info(name: string, age: number, ...reset: any) {
console.log(name, '===name===')
console.log(age, '===age===')
console.log(reset, '===reset===')
return 4
}
info('122', 12, '2442', 12, 421) // 则不受限制
// 像这样
type ParamsType = {
person: string
sex: string
bool: boolean
}
function info(name: string, age: number, ...reset: ParamsType[]) {
console.log(name, '===name===')
console.log(age, '===age===')
console.log(reset, '===reset===')
return 4
}
info('122', 12, { person: '张三', sex: '男', bool: true })
转载自:https://juejin.cn/post/7267470426292404239