您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

typescript基础-做项目了解

ts基础

      • 基本类型
        • boolean、number、string
        • null、undefined
        • any
        • unknown
        • void
        • Array。两种写法(常规写法、泛型写法)
        • Tuple
        • Enum
        • Object
        • never
      • 断言
      • 保护类型(类型守卫)
      • 联合类型(|) 和 交叉类型(&)
      • 接口 interface 和类型别名 type
      • 泛型

基本类型

boolean、number、string

let a1: boolean = true
let a2: number = 3
let a3: string = 'hello world'

null、undefined

对应的类型就是本身;
不开启严格模式的时候可以赋值给任何类型,是任何类型的子类型;
一般会开启,所以只能是自己的类型

let b1: null = null
let b2: undefined = undefined

any

ts 中所有类型都可以使用 any 类型,使用 any 意味着放弃类型校验,除非特殊情况,一般不建议使用

let c1: any = 12
let c2: any = 'hello'
let c3: any = false
let c4: any = null
let c5: any = undefined
let c6: any = function () {}

unknown

为了解决 any 出现的问题所出现的类型;
所有类型都可以是 unknown 类型;
unknown 类型只能赋值给 unknown 或者 any;
不能进行运算、调用属性,当做函数;
使用时把类型具体化,缩小使用范围,则可以避免 any 那些副作用.

// 只能赋值给unknown或者any
let d1: unknown = 1
let d2: any = d1
let d3: unknown = 'hello'
let d4: unknown = d3
// 不能进行运算、属性调用、当做函数
let result = d5 + 1 // error,运算
d5.toString() // 属性调用
d5() // 当做函数
// 使用时把类型具体化,缩小范围
function isString(val: string): void {
  if (typeof val === 'string') {
    val.toString()
  }
}

void

只能当做函数没有返回值时候使用,表示没有任何类型;
函数不加 void,默认返回 void

function showLog(): void {
  console.log('this is show function')
}

Array。两种写法(常规写法、泛型写法)

// 常规写法
let e1:string[] = ['']
let e2:(string|number)[] = ['',12]
// 泛型写法
let e3:Array<string> = ['']
let e4:Array<string | number> = ['',23]
// 数组对象的写法
interface listItem {
    name:string
    age:number
}
let e5:listItem[] = [
    {
        name:'falcon',
        age:20
    }
]
let e6:Array<listItem> = [
    {
        name:'alice',
        age:18
    }
]

Tuple

元组,ts 衍生的一种类型,限制数组的长度和顺序;
已知数组的长度和每个子元素的类型,不能多也不能少

// 可以push已知类型(只能push进去string、number、boolean中的任何一种)的子元素,但无法使用
let f1: [boolean, number, string] = [true, 12, 'hello']
let f2: string = 'world'
f1.push(f2)
console.log(f1) //  [true, 12, "hello", "world"]
console.log(f1[3]) // error.Tuple type '[boolean, number, string]' of length '3' has no element at index '3'.

Enum

为了清晰地表达意图或创建一组有区别的用例

// 数字枚举。自动增长,第一个不初始化赋值会从0开始;枚举可以通过名字和下标访问,值和名字互相映射
// 数字枚举-无初始下标
enum Direction {
    Up,
    Down,
    Left,
    Right
}
console.log(Direction[1]) //'Down'
console.log(Direction['Left']) //2
// 数字枚举-有初始下标
enum Direction1 {
    Up = 2,
    Down,
    Left,
    Right
}
console.log(Direction1[1]) //undefined
console.log(Direction1[3]) //'Down'
console.log(Direction1['Right']) //5
// 字符串枚举。获取值的方式不能使用下标
enum Direction2{
    Up='Up',
    Down='Down',
    Left='Left',
    Right='Right'
}
console.log(Direction2['Left']) // 'Left'
// console.log(Direction2[0]) // error
// 异构枚举。数字和字符串混合使用,几乎不会用,没有意义
enum Direction3 {
    Up='Up',
    Down='Down',
    Left=1,
    Right
}
console.log(Direction3['Up']) //'Up'
console.log(Direction3[2]) //'Right'

Object

非原始数据类型。除 number、string、boolean、undefined、null、symbol 之外的类型

let g1: object = ['hello', 1]
let g2: object = { name: 'falcon', age: 21 }
let g3: object = function () {}
let g4: object = new Date()

never

意味着永远达不到,函数返回值使用,报错、死循环可以做到;
用来校验代码完整性,实现类型的绝对安全,一般很少做这么安全的校验;
never 只能赋值给 never;never 是任意类型的子类型,可以赋值给任意类型

/**
 * 与void的区别:
 * void声明的函数返回空值,never声明的函数永远不返回,死循环或异常
 * void类型可被赋值,但是除never本身外,不能给never赋值
 */
let h1: never
// 对于一个接口,定义某个属性为number,其他都为string
let h2:number = '' as never
let h3:string = '' as never
interface iTypeAge {
    age:number,
}
interface iTypeKeyAny{
    age:never,
    [key:string]:string
}
type iType = iTypeAge | iTypeKeyAny
let h4:iType = {
    name:'falcon',
    age:21,
    times:'many'
}

断言

// 手动断定是什么类型,为了欺骗编辑器,只在编译阶段起作用
// 非空断言。判定某个对象是不是空的,不是undefined或null
let i1:number
i1!+1
function setName(val:string | undefined){
    let newName:string = val!
}
// as语法。将某个类型断定成某个类型
function isNumber(val:number | string){
    (val as number).toFixed()
}

保护类型(类型守卫)

// 运行时的一种检测,当一个变量不确定什么类型的时候,可以调用共有的方法和属性,特有的属性和方法需要配合类型保护
// js - typeof、instanceof、in
// typeof
function getValue(val:number | string){
    if(typeof val === 'number'){
        val.toFixed()
    }
}
// in
type Obj1 = {
    a:number
}
type Obj2 = {
    b:number
}
function isIn(obj:Obj1 | Obj2){
    if('a' in obj){
        console.log(obj.a)
    }
}
// instanceof
type Fn = () => {}
function isFn(fn:Fn |undefined){
    if(fn instanceof Function){
        fn()
    }
}
// ts - is
type Dog = {
    type:'dog',
    eat:() => void
}
type Cat = {
    type:'cat',
    speak:() => {}
}
function getIs(animal:Dog | Cat):animal is Dog{
    return animal.type === 'dog'
}
function isDog(animal:Dog|Cat){
    if(getIs(animal)){
        animal.eat()
    }
}
let animal:Dog = {
    type:'dog',
    eat(){
        console.log('perfect')
    }
}
isDog(animal) // 'perfect'

联合类型(|) 和 交叉类型(&)

// 联合类型
let j1: string | number
// 交叉类型
type JA = string | number
type JB = string | boolean
let j2: JA & JB = 'hello'
// 交叉类型如果是基本类型,合并的时候同名会出现never(即报错)
type JC = {
  a: string,
  b: number,
}
type JD = {
  a: boolean,
  c: string,
}
// let j3:JC&JD = '123' // error

接口 interface 和类型别名 type

// 注:声明interface或type的时候用类型,实现的时候用具体的值
// 接口-描述对象:只读属性、可选属性、任意属性
interface stu{
    name:string, //基本描述
    age:number, //基本描述
    readonly nationality:string, //只读
    hobby?:[string], //可选
    [key:string]:any //任意
}
// 接口-扩展属性:一般使用继承或自动合并
// 自动合并
interface stu{
    flag:boolean,
    level:number
}
// 继承
interface Person extends stu{
    job:string,
    salary:number
}
// 接口-接口字面量赋值。多余属性会报错;通过对象引用赋值的话,会把多余属性擦除,符合就可以赋值
interface Teacher{
    name:string,
    age:number,
    isMarried:boolean
}
let k1:Teacher = {
    name:'falcon',
    age:21,
    isMarried:false,
    // hobby:'running' //多余属性,报错
}
let k2 = {
   name:'falcon',
    age:21,
    isMarried:false,
    hobby:'running'
}
let tea:Teacher = k2 //赋值成功,没有报错
// console.log(tea.hobby) //error,没有该属性,报错

// type,类型别名 - 可用来描述对象、函数,还可以用来描述原始类型、元组、联合类型等
// 数组
type L1 = string[]
type L2 = Array<string>
type L3 = (string|number)[]
type L4 = Array<string | number>
// 对象
type L5 = {name:string,age:number}
// 原始类型
type L6 = string
// 函数
type L7 = () => {} //有返回值
type L8 = () => void //无返回值
// 元组
type L9 = [string,number,boolean]
// 联合类型
type L10 = L9 | L6
/**
 * interface 和 type的区别:
 *  相同:
 *    都可以描述一个对象或者函数
 *    都允许extends扩展
 *  不同:
 *    type可,interface无:
 *      可以声明基本类型、联合类型、元组等
 *      type可以使用 typeof获取的实例的类型 进行赋值
 *      其他:type声明可以用联合类型、看样例
 *    interface可,type无:
 *      interface可以进行声明合并,type只能通过extends进行扩展
 */
// 相同-都可以描述一个对象或者函数
interface User{
    name:string,
    age:number
}
interface setUser{
    (name:string,age:number):void
}
type User1 = {
    name:string,
    age:number
}
type setUser1 = (name:string,age:number) => void
// 相同-都允许extends扩展
// interface扩展interface
interface ifaceUser{
    name:string
}
interface ifaceUser1 extends ifaceUser{
    age:number
}
// type扩展type
type itypeUser = {
    name:string
}
type itypeUser1 = itypeUser & {age:number}
// interface扩展type
type itypePerson = {
    name:string
}
interface ifacePerson extends itypePerson{
    age:number
}
// type扩展interface
interface ifacePerson1 {
    name:string
}
type itypePerson1 = ifacePerson1 & {age:number}

// 不同-type可以声明基本类型、联合类型、元组等
type m1 = string
type m2 = [string,number,boolean]
type m3 = string | number
// 不同-type可以使用 typeof获取的实例的类型 进行赋值
let div = document.createElement('div');
type m4 = typeof div
// 不同-type声明可以用联合类型、看样例
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback<T> = (data: T) => void;
type Pair<T> = [T, T];
type Coordinates = Pair<number>;
type Tree<T> = T | { left: Tree<T>, right: Tree<T> };
// 不同 - interface可以进行声明联合
interface ex1{
    name:string
}
interface ex1{
    age:number
}

泛型

可以使用泛型来创建可重用的组件

// 定义一个函数传递一个参数,函数先把这个参数打印出来,再把该参数返回
function print(arg: string): string {
  console.log(arg)
  return arg
}
// 需求变更,不仅打印string,还要打印number,使用联合类型
function print1(arg: string | number): string | number {
  console.log(arg)
  return arg
}
// 需求再次变更,不仅打印string,还要打印number、boolean、数组等类型(要么使用联合类型把所有类型都罗列出来;要么使用any[不推荐,ts中尽量不要使用any])
// any有弊端,传入和返回值并不是统一,甚至会出现bug:const res:string = print2(123)
function print2(arg: any): any {
  console.log(arg)
  return arg
}
/**
 * 泛型基本使用
 */
// 1-处理函数参数,解决输入输出要一致的问题
function prin3<T>(arg: T): T {
  console.log(arg)
  return arg
}
const res1: string = prin3('hello')
// 指定类型两种方式(定义要使用的类型;ts类型推断,自动推导出类型)
// 定义
prin3 < string > 'hello world'
// 推断
prin3(true)
// 使用泛型来属性interface和type定义的函数类型
// interface
interface isPrint<T> {
  (arg: T): T;
}
const demoPrint: isPrint<string> = function (arg) {
  console.log(arg)
  return arg
}
demoPrint('hello')
// demoPrint(true) // error
// type
type isPrint1<T> = (arg: T) => T
const demoPrint1: isPrint1<number> = function (val) {
  console.log(val)
  return val
}
demoPrint1(123)
// demoPrint1('hello') // error

// 2-默认参数
// interface
interface isShow<T = string> {
  (arg: T): T;
}
const demoShow: isShow = function (arg) {
  console.log(arg)
  return arg
}
demoShow('cute') //默认是string类型
// type
type isShow1<T = number> = (arg: T) => T
const demoShow1: isShow1 = function (val) {
  console.log(val)
  return val
}

// 3-处理多个函数参数
// 一个函数传入了一个只有两项的元组,交换元组顺序后在返回
type tuple = [string, boolean]
let iTuple: tuple = ['hello', false]
function swap<T, U>(tuple: [T, U]): [U, T] {
  return [tuple[1], tuple[0]]
}
console.log(swap(iTuple)) //[false,'hello']

// 4-函数副作用操作
// 一个通用的异步请求方法,根据不同的url请求返回不同类型的数据
// 普通方法
const request = function (url: string) {
  // 此时返回结果为any类型
  return fetch(url).then((res) => res.json())
}
// 改进-使用泛型
function request1<T>(url: string): Promise<T> {
  return fetch(url).then((res) => res.json())
}

/**
 * 约束泛型
 */
// 打印函数传入参数的长度
function isLen<T>(arg:T):T{
    // console.log(T.length)  //报错,不确定T是否有length
    return arg
}
// 和interface结合,来实现约束泛型
interface iLength{
    length:number
}
function isLen1<T extends iLength>(arg:T):T{
    console.log(arg.length)
    return arg
}
isLen1(['hello',true]) //2
// isLen1(false) // error

/**
 * 泛型的一些应用
 */
// 1-泛型约束类
// 有一个栈,有入栈和出栈两种方法,泛型约束入栈和出栈的类型统一
class Stack<T>{
    private data:T[] = []
    push(item:T){
        return this.data.push(item)
    }
    pop():T|undefined{
        return this.data.pop()
    }
}
let demoStack = new Stack<number> ()
demoStack.push(12)
// demoStack.push('hello') //error

// 2-泛型约束接口
// 对interface进行改造,让interface更灵活,定义不同的类型
interface iKeyValue<T,U>{
    key:T,
    value:U
}
let keyDemo1:iKeyValue<string,number> = {key:'hello',value:20}
let keyDemo2:iKeyValue<string,boolean> = {key:'flag',value:true}

// 3-泛型定义数组
let arr1:Array<string> = ['']
let arr2:Array<string|number> = ['',1]

// 4-项目实例,泛型约束后端接口参数类型
// keyof用于获取某种类型的所有键,返回的是联合类型。extends约束T必须是keyof API联合类型的子类型

interface API {
    '/book/detail': {
        id: number,
    },
    '/book/comment': {
        id: number
        comment: string
    }
}
function axiosRequest<T extends keyof API>(url:string,obj:API[T]){
    return axios.post(url,obj)
}
axiosRequest('/book/comment',{id:1,comment:'nice'})

分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进