个人向TS笔记

TypeScript是JavaScript的超集,为JS增加了类型支持。
  目的:在编译的时候检索错误,提前发现错误减少找bug改bug的时间。代码提示更多。维护性更强。支持最新的ECMAScript语法。
安装:npm i -g typescript    Node.js和浏览器只认JS代码,要将TS转为JS才能执行        tsc hello.ts(将TS编译为JS)
简化TS运行步骤:安装 npm i -g ts-node        ts-node hello.ts(不会生成js文件)
TS会检查变量类型的变化,而JS不会
类型注解:    :number(e为变量添加类型约束)
JS类型:原始类型(number/string/boolean/null/undefined/symbol)=》Symbol是ES6中引入的一种新的基本数据类型,用于表示一个独一无二的值。
    对象类型 object(包括数组、对象、函数等对象)
TS新增类型:联合类型、自定义类型(类型别名)、接口、元组、字面量类型、枚举、void、any等
    let s:symbol = Symbol()
    let numbers:number[] = [1,3,5]    (推荐写法,效果和下一行相同)
    let strings:Array<string> = ['1','2','3']
    let arr:(number | string)[] = [1,2,'a'](联合类型,数组内支持number和string)
    类型别名:type CustomArray = (number | string | null)[]
        let arr1:CustomArray = [1,2,'a',null]
函数:const add = (num1:number,num2:number):number => {
          return num1 + num2
    }
    等价于=》const add:(num1:number,num2:number) => number = (num1,num2) => {
              return num1 + num2
        }
    若函数没有返回值,需要指定返回值类型为void
    function mySlice(start?:number,end?:number) {    //属性后加?:用以判断该属性是否可选,可选参数后不能出现必选参数
          console.log("起始索引",start,"结束索引",end)
    }
对象类型:
let person: {name:string,age:number,sayHi():void,greet(name:string):void} = {
  name:'zs',
  age:18,
  sayHi() {},
  greet(name) {},

let person: {
  name:string
  age:number
  sayHi:() => void
  greet(name:string):void
} = {
  name:'zs',
  age:18,
  sayHi() {},
  greet(name) {},

接口:interface IPerson {
          name:string
          age:number
          sayHi():void
    }(相比type类型别名,接口只能为对象指定类型)
接口继承 :(P2继承P1属性)interface P1 {x:number,y:number}        interface P2 extends P1 {z:number}
元组:let position:[number,string] = [1,'333'](约束数组内元素数量、类型)
声明变量并初始化、决定函数返回值时,发生了类型推论,可以省略类型注解。
类型断言: 使用as关键字实现类型断言
    const alink = document.getElementById('link') as HTMLAnchorElement
    const alink = <HTMLAnchorElement>document.getElementById('link')
字面量类型:(const定义的常量,它的值不能变换)多用于数据明确不变更的情况
    let str1 = "Hello TS"    类型=》srting
    const str2 = "Hello TS"    类型=》"Hello TS"
字面量类型配合联合类型一起使用:const changDirection = (direction:'up'|'down'|'left'|'right')=>{}
    等价于枚举(一般推荐使用字面量类型+联合类型组合的方式,更加直观,但枚举提供值 )
枚举:(枚举的值默认从0开始,指定值后按指定值累加)
    enum Direction {up, down,left,right}
    const changDirection = (direction:Direction)=>{ }
    changDirection(Direction.up)//访问直接通过  (.)语法访问枚举成员  
枚举成员有默认值(值为数字的称为数字枚举),从0开始自增,也可以设置初始化值
    enum Direction {up=2, down=4,left=6,right=8}
   字符串枚举:枚举成员的值是字符串。字符串枚举后面的每个成员必选有初始值
    enum Direction {up, down='1',left=4,right}
   编译为JS代码时,其他类型会被自动移除,枚举类型会被编译成JS代码
any类型:不推荐使用any,会失去类型保护,可以临时使用
    隐式具有any的情况(1.声明变量不提供类似和默认值。2.函数参数不加类型)
typeof:TS的typeof可以在类型上下文中引用变量或属性的类型
    let p = {x:1,y:2}
    function formatpoint(point:typeof p) {}
    formatpoint({x:3,y:4})

TypeScript高级类型
class类:TS中的class,不仅提供了class的语法功能,也作为一种类型存在。
class Person {
  age:number
  gender:string
  constructor(age:number,gender:string) {//构造函数不能指定返回值类型,用以指定初始值
    this.age = age
    this.gender = gender
  }
}
const p = new Person(22,'man')

类的继承:类继承的两种方式implements(实现接口)、extends(继承父类)
    JS中只有extends,implements是TS提供
    class A {}    class B extends A {}    或者        interface A {}    class B implements A{}//B类必须提供A接口中指定的所有方法和属性
类成员可见性:可以使用TS来控制class的方法或属性对于class外的代码是否可见。
    public(公有的,默认)、protected(受保护的,只能在当前类和子类中调用)、private(私有的,只能在当前类调用,也无法通过实例来访问)
readonly(只读修饰符):防止在构造函数之外对属性进行赋值,只能修饰属性而不能修饰方法
class Person {
  readonly age:number = 2//不添加类型约束,age会变成字面量类型
  constructor(age:number) {
    this.age = age
  }
}
类型兼容性:TS采用结构化类型系统,类型检查只要值所具有的形状相同就属于同一类型。成员不同时,成员多的可以赋值给少的(class和接口的兼容性差不多,接口兼容报错,需要赋初始值)
    class A { x:number,y:number}
    class B {x:number,y:number,z:string}
    const a:A = new B()
函数之间兼容性:参数少的可以赋值给参数多的、相同位置的参数类型要相同、只关注返回值类型本身
交叉类型(&):类似于接口继承,用于组合多个类型为一个类型(常用于对象类型)
    interface Person {name:string}
    interface Contact {phone:number}
    type PersonDetail = Person & Contact
   交叉类型可以处理含同名属性的类型冲突( | ),接口继承报错

泛型<>:相较于any,泛型在保证类型安全前提下,让函数等于多种类型一起工作,从而实现复用(常用于函数、接口、class)
    function id<Type>(value:Type):Type {return value}
    const num = id<number>(10)
    const str = id<string>("hello")
    简化调用:const num = id(10)、const num = id("hello")类型推断为字面量id和hello
泛型约束:不添加类型约束导致无法访问任何属性(如数组的length)
    function id<Type>(value:Type[]):Type[] { value.length    return value}(指定更加具体的类型)
    interface ILength {length:number}//添加约束
    function id<Type extends ILength>(value:Type):Type {
          value.length
          return value
    }
    id(['1',2,3])    id('123123')    id({length:12,name:'zs'})(传入的实参只要有length属性即可)
   添加多个类型变量,并且变量之间还可以约束
   function getProp<Type,Key extends keyof Type>(obj:Type,key:Key) {
     return obj[key]
   }
   getProp({name:'jack',age:22},'age')    getProp({name:'jack',age:22},'name')    getProp('abc',1)//1表示索引
    keyof关键字接收一个对象类型,生成其键名称(可能是字符串或数字)的联合类型
泛型接口:需要显示指定具体的类型没有类型推断
    interface IdFunc<Type> {
      id:(value:Type) => Type
      ids:() => Type[]
    }
    let obj:IdFunc<number> = {
      id(value) {
        return value
      },
      ids() {
        return [1,2,3]
      }
    }
泛型类
    class Person<NumType> {
      defaultValue:NumType
      add:(x:NumType,y:NumType) => NumType
      constructor(value:NumType) {
        this.defaultValue = value
      }
    }
const myNum = new Person<number>(10)
const myNum = new Person(10)//加了constructor可以省略<类型>不写
myNum.defaultValue = 10
泛型工具类型:
1.Partial<Type>用来构造(创建)一个类型,将Type的所有属性设置为可选。
    interface Props {
      id:string
      children:number[]
    }
    type PartialProps = Partial<Props>
    let p1:Props = {
      id:'123',
      children:[1,2,3]
    }
    let p2:PartialProps = {//可以不传值,属性都是可选的
      id:'1'
    }
2.Readonly<Type>用来构造一个类型,将Type的所有属性都设置为Readonly(只读)
    type ReadonlyProps = Readonly<Props>
3.Pick<Type,Keys>从Type中选择一组属性来构造新类型。第二个类型变量传入的属性只能是第一个类型变量中存在的属性
    interface Props {
          id:string
          title:string
          children:number[]
    }
    type PickProps = Pick<Props,'id'|'title'>
4.Record<Keys,Type>构造一个对象类型,属性键为Keys,属性类型为Type。前者表示对象有哪些类型,后者表示对象属性的类型
    type RecordObj = Record<'a'|'b'|'c',string[]>
    type RecordObj = {//等价于上式
      a:string[]
      b:string[]
      c:string[]
    }
    let obj:RecordObj = {
      a:['a'],
      b:['b'],
      c:['c']
    }
索引签名类型:(无法确定对象中有哪些属性,或对象中可能出现任意多个属性
    interface AnyObject {
      [key:string]:number//前置知识:JS中对象({})的键是string类型的。key:string可以代表对象所有属性的键
    }
    let obj:AnyObject = {
      a:1,
      b:12,
      c:123
    }
    interface MyArray<T> {
      [index:number]:T//数组的索引(键)是number类型
    }
    let arr1:MyArray<number> = [1,2,3]
映射类型:基于旧类型创建新类型(对象类型),减少重复、提示开发效率。    注意:映射类型只能在类型别名中使用,不能在接口中使用。
    //根据联合类型创建
    type PropKeys = 'x'|'y'|'z'
    type Type1 = {x:number,y:number,z:number}
    type Type2 = {[Key in PropKeys]:number}//映射
    //根据对象类型创建。keyof Props获取到对象类型Props中所有键的联合类型,key in Props表示可以是Props中所有的键名中的任意一个
    type Props = {a:number,b:string,c:null}
    type Type3 = {[key in keyof Props]:number}
T[p]语法(索引查询类型):查询属性的类型,T是对象,p是对象的属性
    type Props = {a:number,b:string,c:null}
    type TypeA =  Props['a']
    type MyPartial<T> = {//模拟Partial类型
      [P in keyof T]?:T[P]
    }
    type PartialProps = MyPartial<Props>
    //同时查询多个索引的类型
    type Props = {a:number,b:string,c:null}
    type TypeA =  Props['a'|'b']
    type TypeB =  Props[keyof Props]

类型声明文件: .d.ts=》只包含类型信息的类型声明文件,仅用于提供类型信息,为JS提供类型信息
为已有JS文件提供类型说明:如通过ts-loader处理.ts文件

通过命令行编译ts:tsc .\hello.ts --target es6(指定了文件名,将忽略tsconfig.json文件)
创建支持TS的项目命令(React):npx create-react-app 项目名称 --template typescript    npm start启动
react-app-env.d.ts:React项目默认的类型声明文件。
三斜线指令:指定依赖的其他类型声明文件,types表示依赖的类型声明文件包的名称。
    /// <reference types="react-scripts" />

React是组件化开发模式,React开发主要任务就是写组件(函数组件、class组件)
1.函数组件
    type Props = {name:string,age?:number}
    // const Hello:FC<Props> = ({name,age}) => (
    //   <div>你好,我叫{name},今年{age}岁了</div>
    // )
    Hello.defaultProps = {
      age:223//使用了FC,添加默认值
    }
    //简化
    const Hello = ({name,age}:Props) => (
      <div>你好,我叫{name},今年{age}岁了</div>
    )
    const Hello= ({name,age=21}:Props) => (//加默认值
      <div>你好,我叫{name},今年{age}岁了</div>
    )

    const Hello = ({name,age=18}:Props) => {
      const onClick = (e:React.MouseEvent<HTMLButtonElement>) => {
        console.log("赞",e.currentTarget); 
      }
      const onChange = (e:React.ChangeEvent<HTMLInputElement>) => {
        console.log("赞~~~",e.target.value); 
      }
      return (
        <div>
          你好,我叫{name},今年{age}岁了
          <button onClick={onClick}>点赞</button>
          <input type="text" onChange={e => {}}/>
        </div>
      )
    }
    //在JSX中写事件处理程序(e => {}),然后鼠标放到e上,可以利用TS类型推断来查看事件对象类型
          <input type="text" onChange={e => {}}/>
2.class组件
class组件的类型
    type State = {count:number}
    type Props = {message?:string}
    class C1 extends React.Component {}//无Props、Stata
    class C2 extends React.Component<Props> {}//有Props、无Stata
    class C3 extends React.Component<{},State> {}//无Props、有Stata
    class C4 extends React.Component<Props,State> {}//有Props、Stata
class组件的属性和属性默认值
    type Props = {name:string,age?:number}
    class Hello extends React.Component<Props> {
      render() {
        const {name,age=18} = this.props//添加属性默认值
        return (
          <div>你好,我叫{name},今年{age}岁了</div>
        )
      }
    }
class组件状态(state)和事件
    type State = {count:number}
    class Counter extends React.Component<{},State> {//添加了初始化类型state,下面调用count才有类型提示
      state:State = {
        count:0
      }
      handlerClick = () => {
        this.setState({
          count:this.state.count+1
        })
      }
      render(): React.ReactNode {
        return (
          <div>
            计数器:{this.state.count}
            <button onClick={this.handlerClick}>+1</button>
          </div>
        )
      }
    }

.footer:before {
    content: '';
    position: absolute;
    right: 0;
    bottom: 0;
    left: 0;
    height: 50px;
    overflow: hidden;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
                0 8px 0 -3px #f6f6f6,
                0 9px 1px -3px rgba(0, 0, 0, 0.2),
                0 16px 0 -6px #f6f6f6,
                0 17px 2px -6px rgba(0, 0, 0, 0.2);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值