TS教程-小白也能秒懂的TS入门指南,跟上程序员的脚步!

小白也能秒懂的TS入门指南,跟上程序员的脚步!

  • TS的定义
  • 安装TS
  • 八大基础类型
    • number、string、boolean
    • null、undefined
    • function
    • symbol、bigint
  • any
  • unknown
    • any、unknown 区别
  • void
  • never
  • 数组
  • 元组
  • 枚举
    • 数字枚举
    • 字符串枚举
    • 异构枚举
    • 普通枚举
    • 常数枚举 (const enum 定义的枚举)
    • 接口使用
  • as const
    • 不强制类型转换
    • 强制类型转换
  • 待更新

最近项目使用了Vue3.0,当然啦,就使用了TS,由于赶进度,并没有仔细的去了解他,现在系统的看看咯!
TS教程-小白也能秒懂的TS入门指南,跟上程序员的脚步!_第1张图片

TS的定义

TypeScript是一种由微软开发的自由和开源的编程语言。 它是 JavaScript
的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。

  • js 有的 ts 都有,所有js 代码都可以在 ts 里面运行。
  • ts 支持类型支持,ts = type +JavaScript。
  • ts 完全支持 js ,可以直接转换
js ts
动态编程语言 静态编程语言
边解释边执行,错误只有在运行的时候才能发现 先编译再执行,在写的时候就会发现错误了(ts不能直接执行,需要先编译成 js )

安装TS

npm i  -g  typescript

yarn  global add  typescript 

八大基础类型

let name: string = "ll";
let age: number = 18;
let isShow: boolean = true;
let hoh: undefined = undefined;
let nwn: null = null;
let obj: object = {name: 'll', age: 18};
let big: bigint = 100n;
let sym: symbol = Symbol("ll"); 

number、string、boolean

//number
let age: number = 18   

//string
let name: string = 'll'             
let nickname: string = `A ${name}`   // 支持模板字符串

//boolean 
let bol: boolean = true;

null、undefined

//undefined
let box:undefined = undefined
//null
let box:null = null    
  • 默认情况下 null 和 undefined 是所有类型的子类型
  • 你可以把 null 和 undefined 赋值给 number 类型的变量。
let age: number = null
let name: string = undefined
  • 然而,当你启用strictNullChecks,null和undefined只能赋值给void和本身对应的类型。比如:
let x: number;
x = 1; // 运行正确
x = undefined;    // 运行错误
x = null;    // 运行错误

//如果你非要改的话,你可以使用联合类型string | null | undefined。
let x: number | null | undefined;
x = 1; // 运行正确
x = undefined;    // 运行正确
x = null;    // 运行正确
  • strictNullChecks标记启用
//tsconfig.json
{
  "compilerOptions": { //编译选项,可以被忽略,这时编译器会使用默认值
     "strictNullChecks": false,
      //在严格的null检查模式下,null和undefined值不包含在任何类型里,只允许赋值给void和本身对应的类型。
        }
  }

function

TS 定义函数类型需要定义输入参数类型和输出类型。
输出类型也可以忽略,因为 TS 能够根据返回语句自动推断出返回值类型。
函数没有明确返回值,默认返回 Void 类型

  • 函数写法

const fn1 = (param:string): void => {
  console.log("给我传的值必须是字符哟");
  console.log("我是没有返回值的箭头函数");
};

function fn2(param:string): void {
  console.log("给我传的值必须是字符哟");
  console.log("我是没有返回值的函数");
}
  • 函数表达式写法

let fn3= (x: number, y: number): number => {
    console.log("给我传的值必须是数字哟");
    console.log("我的返回值的也是数字哟");
    return x + y
}
  • 可选参数
//参数后加个问号,代表是可选参数,
//可选参数必须要放在函数入参的最后面,不然会导致编译错误。
function fn4(x:number, y:number, z?:number):number {
     console.log("给我传的值必须是数字x和y哟,你可以选择传数字z也可以不传哟");
    return x + y
}
  • 默认参数
let fn5= (x: number, y: number=100): number => {
    return x + y
}
fn5(100)
  • 注意,如果带默认值的参数不是最后一个参数,用户必须明确的传入 undefined值来获得默认值。
let fn6= (x: number=100, y: number): number => {
    return x + y
}
fn6(100) //报错 编译器会判定你只传了 x,没传 y。
fn6(undefined,100)
  • 剩余参数
function fn7(...args:number[]):number[]{
  return args
}
console.log(f8(1,2,3,4,5))//[1,2,3,4,5]

symbol、bigint

const sym1:symbol = Symbol(); //唯一值
let big: bigint = 100n //目前兼容性不是很好

any

可以赋予任意类型的值,可以在任意值上访问任何属性,调用任何方法,相当于Js

//不建议使用,因为这将丧失TS本来的意义
let anyNever: any = 4
anyNever= "ll" 
anyNever= false 
anyNever.name        
anyNever.getName()
  • any吸收一切类型,如果任一组成类型是any,则联合类型相当于any
 type anyNever1 = unknown | any;  // any
 type anyNever2 = number| any;  // any
 type anyNever3 = string| any;  // any

unknown

未知类型的值,需要进行类型检查或类型断言才能使用, 不可以在任意值上访问属性,调用方法,且unknown类型的值不能直接赋值给其他变量

  • unknownNever是unknown类型,因此不能确定该值是否有方法、属性,不能通过语法检查。
//unknown
let unknownNever:unknown="冷月心"
unknownNever.getName();//报错
unknownNever.name//报错
  • param是unknown类型,因为不知道 param 的类型,使用运算符 /,导致报错
function divide(param: unknown) {
  return param / 2;
}
//1.类型断言解决
function divide(param: unknown) {
  return param as number / 2;
}

// 2、类型守卫 —— 不飘红,且确保正常执行
function divide(param: unknown) {
if (typeof param === 'number') {
     // 推断出类型: number
     return param / 2;
 }
}

 // 3、类型断言函数,抛出错误 —— 不飘红,且确保正常执行
 function divide(param: unknown) {
 assertIsNumber(param);
 return param / 2;
}
/** 类型断言函数,抛出错误 */
function assertIsNumber(arg: unknown): asserts arg is Number {
    if (!(arg instanceof Number)) {
        thrownewTypeError('Not a Number: ' + arg);
    }
 }

  • unknown类型的值也不能赋值给any和unknown以外的类型变量
let strVal: string
strVal = 'str'
strval = unknownNever// TS2322: Type 'unknown' is not assignable to type 'string'. 

  • 在联合类型中,unknown吸收除any以外任何类型。即如果任一组成类型是unknown,联合类型也会相当于unknown
type unknownNever1 = unknown | null;       // unknown
type unknownNever2 = unknown | undefined;  // unknown
type unknownNever3 = unknown | string;     // unknown
type unknownNever4 = unknown | any;       // any

any、unknown 区别

any unknown
可以赋予任意类型的值 未知类型的值,需要进行类型检查或类型断言才能使用
可以在任意值上访问任何属性,调用任何方法 不可以在任意值上访问属性,调用方法,且unknown类型的值不能直接赋值给其他变量

void

没有任何类型。

  • 没有返回值的函数可以用void声明

const fn1 = (param:string): void => {
  console.log("我是没有返回值的函数");
};
  • 也可以用来声明变量,但只能作用在undefined。
const u:void=undefined;//用法很无语,基本不会这么用
const n:void=null;//这样会报错,只有tsconfig.json中strictNullChecks属性设置为false时,null才能赋值给void
const age:void=18;//这样也会报错

never

永不存在的值的类型

  • 如果一个函数执行时抛出了异常,那么这个函数永远不存在返回值,因为抛出异常会直接中断程序运行。
// 异常
function fn(msg: string): never { 
  throw new Error(msg)

  • 函数中执行无限循环的代码,使得程序永远无法运行到函数返回值那一步。

// 死循环 千万别这么写,会内存溢出
function fn(): never { 
  while (true) {}
  • never 能够表示任何类型的子类型,所以能够赋值给任何类型。(bottom type)
 let err: never;
 let num: number = 4;
 num = err; // OK

数组

  • 数组类型语法: let 变量名 : 数据类型[] = [值1,值2,值3]
let arr1 : number[] = [1,2,3,4]
let arr2: Array<number> = [1, 2, 3]; 
let arr3: Array<number> = new Array(4); // 表示定义一个数组的长度,一般固定一个数组的长度时这个方法比较方便
let arr4 = new Array<number>(4) //这种写法和 arr3 效果是一样的

// interface 定义
interface NumberArray {
    [index: number]: number;
}
let arr5: NumberArray = [1, 2, 3];

  • 使用泛型语法 :let 变量名 : Array<数据类型> = [值1,值2,值3]
let arr2 : Array<number> = [5,6,7,8]
//数组定义后,数组内的数据类型必须和定义数组的时候的类型是一致的,否则会有错误提示,某些情况下不会编译通过。

let arr2 : Array<number> = [true,'HAHA'] //报错

元组

元组类型就是在定义数组的时候,类型和数据的个数一开始就已经限定好了。

  • 元组类型的语法 :let arr : [ string ,number,boolean ] = [ ‘跳跳’ , 520, true ]
let arr1 : [string,number,boolean] =  [ '跳跳' , 520, true ]

//元组类型在使用的时候,数据的类型的位置和数据的个数,需要和在定义元组的时候的数据类型和位置相一致,不一致则会报错提示
let arr2 : [string,number,boolean] = ['跳跳',true,520]  // 报错

//可以对元组内的值进行更改
let arr3 : [string,number,boolean] = ['跳跳',520.123,true] 
console.log(arr3[1].toFixed(2));  // 520.12 保留两位小数
  • 利用函数动态拼合一个元组

function useFetch() {
    const name: string = "跳跳";
    const age: number = 18;
    return [name, age] as const;
    }
//这里如果不使用 as const 会发现 我们结构出来的数组类型是name: string | number
// 使用完 as const 以后 为string,as const 也叫类型断言
  • 数组转化元组 泛型
function useFetch2() {
    const response: string = "Barry";
    const age: number = 25;
    return tuplify(response, age)
}
 
function tuplify<T extends unknown[]>(...elements: T): T {
    return elements;
}

枚举

枚举允许开发者定义一组命名的常量。使用枚举可以使其更容易记录意图,或创建一组不同的情况。TypeScript提供了基于数字和字符串的枚举。

数字枚举

//数字枚举如果没有初始化,默认初始化值为0,每项+1
enum Direction {
    Up, // 0
    Down,// 1
    Left,// 2
    Right// 3
}

//如果有初始化或被赋值,则在初始化值的基础上,每项+1
enum Direction {
    Up = 1,// 1
    Down,// 2
    Left,// 3
    Right// 4
}

//如果未手动赋值的枚举项与手动赋值的重复了,TypeScript 是不会察觉到这一点的,但建议尽量避免
enum Days {Sun = 3, Mon = 1, Tue, Wed, Thu, Fri, Sat};
 
console.log(Days["Sun"] === 3); // true
console.log(Days["Wed"] === 3); // true
console.log(Days[3] === "Sun"); // false
console.log(Days[3] === "Wed"); // true
  • 反向映射

除了创建一个以属性名做为对象成员的对象之外,数字枚举成员(字符串枚举成员没有反向映射)还具有了 反向映射,从枚举值到枚举名字

enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};
 
console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
 
console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true

字符串枚举

在一个字符串枚举里,每个成员都必须用字符串字面量,或另外一个字符串枚举成员进行初始化。

enum Direction {
    Up = "UP",
    Down = "DOWN",
    Left = "LEFT",
    Right = "RIGHT",
}

异构枚举

数字和字符串混用,不推荐!

enum BooleanLikeHeterogeneousEnum {
    No = 0,
    Yes = "YES",
}

普通枚举

//没有初始化器的枚举要么需要放在第一位,要么必须放在用数字常量或其他常量枚举成员初始化的数字枚举之后
//上述代码会报错,因为Red是计算项,而Green紧接其后却无法获取初始值
enum Color {Red = "red".length, Green, Blue};

常数枚举 (const enum 定义的枚举)

常数枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员,假如包含了计算成员,则会在编译阶段报错

const enum Directions {
    Up,
    Down,
    Left,
    Right
}
let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];

//编译为
var directions = [0 , 1, 2 , 3];

接口使用

/**
 * 用于定义一些带名字的常量
 * 后台管理系统 下面用枚举定义一些角色类型
 */
enum role{
    stu=1,//如果不加1 默认排序从0开始 
    teacher,
    footer,
    admin
}
//字符串枚举
enum message{
    success="恭喜你,成功了",
    fail="抱歉,失败了"
}
//异构枚举 有数字和字符串
enum Answer{
    N,//数字 默认为0
    Y="我是字符串"
}

as const

不强制类型转换

as const 被称为 const 类型断言,const 类型断言告诉编译器,要将这个表达式推断为最具体的类型,如果不使用它的话,编译器会使用默认的类型推断行为,可能会把表达式推断为更通用的类型。

强制类型转换

// 强制类型转换
 
function getLength(str: string | number): number {
     if((<String>str).length)
    // 或
     if ((str as string).length) {
        return (<String>str).length
    } else {
        return str.toString().length;
    }
}

待更新

你可能感兴趣的:(前端)