TS安装、TS八大基础类型、TS元组、枚举和断言

TS的概念

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

js 有的 ts 都有,所有js 代码都可以在 ts 里面运行滴。
ts 支持类型支持,ts = type +JavaScript。
ts 完全支持 js ,可以直接转换。

JsTs
动态编程语言静态编程语言
边解释边执行,错误只有在运行的时候才能发现先编译再执行,在写的时候就会发现错误了(ts不能直接执行,需要先编译成 js )

安装TS

命令行安装

npm i  -g  typescript

yarn  global add  typescript 

TS八大基础类型

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 区别

anyunknown
可以赋予任意类型的值未知类型的值,需要进行类型检查或类型断言才能使用
可以在任意值上访问任何属性,调用任何方法不可以在任意值上访问属性,调用方法,且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;
    }
}

断言

语法:
有两种写法:值 as 类型 或 <类型>值

as 类型 
//或
<类型>

将一个联合类型断言为其中一个类型
当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型中共有的属性或方法:

interface Cat {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}
function getName(animal: Cat | Fish) {
    return animal.name;
}
//想访问animal.swim
function isFish(animal: Cat | Fish) {
    if (typeof animal.swim === 'function') {
        return true;
    }
    return false;
} //会报错

//此时可以使用类型断言,将 animal 断言成 Fish:
function isFish(animal: Cat | Fish) {
    if (typeof (animal as Fish).swim === 'function') {
        return true;
    }
    return false;
}

类型断言
类型断言有两种写法:1.“尖括号”语法(<数据类型>变量)2.变量 as 数据类型
在这里插入图片描述
使用类型断言例子:
有时候你会比 TS 更加明确一个值的类型,
此时,可以使用类型断言来指定更具体的类型。
比如,
在这里插入图片描述

注意:getElementById 方法返回值的类型是 HTMLElement,该类型只包含所有标签公共的属性或方法,不包含 a 标签特有的 href 等属性。
因此,这个类型太宽泛(不具体),无法操作 href 等 a 标签特有的属性或方法。
解决方式:这种情况下就需要使用类型断言指定更加具体的类型。

使用
使用类型断言:

解释:
在这里插入图片描述
使用 as 关键字实现类型断言。
关键字 as 后面的类型是一个更加具体的类型(HTMLAnchorElement 是 HTMLElement 的子类型)。
通过类型断言,aLink 的类型变得更加具体,这样就可以访问 a 标签特有的属性或方法了。
另一种语法,使用 <> 语法,这种语法形式不常用知道即可:
在这里插入图片描述
技巧:在浏览器控制台,通过 console.dir() 打印 DOM 元素,在属性列表的最后面,即可看到该元素的类型

  • 26
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值