相关文章推荐
慷慨大方的薯片  ·  react ...·  1 月前    · 
潇洒的伤疤  ·  設定 CORS Proxy ...·  4 天前    · 
温暖的雪糕  ·  Enum.Parse 方法 ...·  8 月前    · 
俊逸的杯子  ·  Error message ...·  1 年前    · 
坐怀不乱的蚂蚁  ·  Get-Counter ...·  1 年前    · 
public name: string; //类里面 子类 其它任何地方外边都可以访问 protected age: number; //类里面 子类 都可以访问,其它任何地方不能访问 private money: number; //类里面可以访问, 子类和其它任何地方都不可以访问

安装 TypeScript 时,会顺带安装 lib.d.ts 声明文件。此文件包含了 JavaScript 运行时以及 DOM 中存在各种常见的环境声明

对于项目中一些全局可用的变量或者接口,可以考虑创建一个globals.d.ts

globals.d.ts 可以看做是 lib.d.ts 的扩充

TypeScript的核心原则之一是对值所具有的结构进行类型检查

在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。

interface props {
  readonly name: string
  habit? : string

函数 && 接口

定义一个函数所需的形状

interface fnBox {
  (len:number, cont: number): number[]    
let pushAry:fnBox
pushAry = function (len: number, cont: number) {
  return new Array(len).fill(cont)    

如果这里故意写错cont的类型,会有什么提示

可以定义无返回值的函数

interface props {
  once(): void 
  twice: () => void 
  • 函数表达式
  • 我们也可以使用函数表达式去书写函数

    let sing = () => {-- do something --}
    

    函数表达式添加约束可以写为

    let sing = (singer: string): boolean => {-- do something --}
    

    但是这种只是对等号右侧的匿名函数进行了类型定义,而等号左边的 sing,是通过赋值操作进行类型推论而推断出来的

    手动给 sing 添加类型,则应该是这样:

    let sing: (singer: string) => boolean = (singer: string): boolean => { -- do something-- }
    

    implements 可以使类 具有接口的属性功能

    interface int2 {
      once(): void,
      touchMore: (count: number) => void
    class Btn implements int2 {
      once () {
        console.log('once')
      touchMore (count: number) {
        console.log('touchMore')
    const btns = new Btn
    btns.once()
    btns.touchMore(9)
    

    class

    配置 tsconfig.json

    1 使用webpack搭建项目的时候,有配置alias参数

    'utils': path.resolve(__dirname, '../utils')
    

    这样在组件中引入的时候,文件路径可以简化

    import { log } from 'utils/statistics'
    

    不过在使用ts之后,会发现组件中有警告信息,表示找不到此模块

    就需要另外在tsconfig中添加配置参数

        "baseUrl": "./",
        "paths": {
          "components": ["./components/*"],
          "utils": ["./utils/*"],
    

    2 other

    noEmitOnError: true
    

    当编译出错,则不输出编译后的文件

    全局变量 window

    在访问页面的时候,server会反馈一些基本的用户信息,比如用户名,设备版本号等,将这些全部挂载在CONFIG变量中了

    <script type="text/javascript">
      window.CONFIG = JSON.parse(decodeURIComponent('{{feConfig}}'))
    </script>
    const {uid, version} = window.CONFIG // 然后在组件中可以直接获取
    

    但是在加入TS之后,会提示window中不存在属性CONFIG

    TS不允许获取,设置没有声明过的属性,所以这里报错了

    1 全局扩展

    在模块内部添加声明到全局作用域

    在入口文件index.tsx中 添加声明

     declare global {
       interface Window { CONFIG: any }
     const {uid} = window.CONFIG
    

    2 使用类型断言

    const { apk } = (window as any).CONFIG
    

    3 添加 globals.d.ts 声明文件

    interface Window {
      CONFIG: any
    
    import * as React from 'react'
    class App extends React.Component<props, state>{
        -- do something --
    

    泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性

    比如写一个根据指定内容填充到指定长度的数组生成函数 getAry

    function getAry (len: number, cont: string | number): string[] | number[] {
      return new Array(len).fill(cont)
    
    function createFn<T>
    function createFn<string> // 明确指定 T 是 string 类型的
    

    其实泛型函数的类型与非泛型函数的类型没什么不同,只是多了一个类型参数在最前面

  • 可以指定默认类型
  • TypeScript 2.3 以后,我们可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,从实际值参数中也无法推测出时,这个默认类型就会起作用

    function beConfusion<T = boolean> (name: string, isDone: boolean) {...}
    

    将上面那个函数使用接口来定义

    interface dealFn {
      <T>(len: number, cont: T): T[]    
    let getAry: dealFn
    getAry = function <T> (len: number, cont: T): T[] {
     --do something--    
    

    泛型类使用<>括起泛型类型,跟在类名后面

    class DealAry<T> {
      value: T
      constructor (value: T) {
        this.value = value
      deal () {
        console.log(this.value)
    

    other

  • 其余的一些泛型变量
  • 虽然可以自己定义泛型变量结构,但是一般会使用已定义好的泛型

    Promise

    async taobaoGoods =  function (ids: number[]): Promise<string> {
      return new Promise <string>((reslove, reject) => {
        try{
          reslove('success')
        } catch {
          reject('failture')
    
  • 可以有多个泛型变量
  • class 
    

    React.component 类的泛型变量

    打开 node_modules/@types/react 可以看到 component 类

    简单概括就是

    class Component<P = {} , S = {} > {
      -- other --
      readonly props: Readonly<{ children?: ReactNode }> & Readonly<P>
      state: Readonly<S>
      -- other --
    

    可以看到 props 和 state 两个对象都是只读的

    所以我们在写React组件的时候,要调整为

    interface BannerProps {
      showUpdate(): void,
      clickOnce: (type: string, id: number) => void
    interface BannerState {
      once: boolean
    export default class Banner extends React.Component<BannerProps, BannerState> {
      --do something--
    

    获取一个元素的某个属性

    componentDidMount () {
      const target = this.refs.img
      if (target.getAttribute('src') != newSrc) { -- do something-- }   
    

    ts提示有错误

    这是因为TS推断target 还不具备getAttribute 属性

    TypeScript 允许你覆盖它的推断,并且能以你任何你想要的方式分析它,这种机制,被称为「类型断言」

    TypeScript 类型断言用来告诉编译器你比它更了解这个类型,并且它不应该再发出错误

    <类型>值 或者 值 as 类型
    

    *** 在jsx中必须使用 第二种方式去处理 ***

    在不确定类型的时候就访问其中一个类型的属性或方法,可以使用类型断言

    function getType (arg: string | boolean): boolean {
      if ( arg.length ) return true
      return false
    

    这种其实会报错的,如果输入是布尔值,则没有length

    加入类型断言

    function getType (arg: string | boolean): boolean {
      if ( (arg as string).length  ) return true
      //  if ( (<string>arg).length ) return true
      return false
    

    断言成一个联合类型中不存在的类型是不允许的

     if ( (arg as array).length  ) return true // 报错
    

    所以上面组件里 需要调整为

    const target = this.refs.img as HTMLElement 
    

    JavaScript 中有很多内置对象,可以直接在 TypeScript 中当做定义好了的类型

    const isEnd:Boolean = new Boolean(false)
    interface createEle {
      createElement(tagName: "div"): HTMLDivElement    
    

    设置组件属性

    interface videoProps {
        poster?: string
    class Video extends Component<videoProps> {
        static defaultProps = {
            poster: ''
    

    webpack 调整为 ts 格式

    新项目中将webpack部分调整为ts处理

    参考文章,官网地址

    ts-node 可以直接运行.ts文件 ts版本使用方式见官网

    tsconfig

    tsconfig.webpack.json中的配置直接按照官网中去写的

    "compilerOptions": { "module": "commonjs", "target": "es5", "esModuleInterop": true

    这里配置的是es5 将其调整为es6即可

    或者使用 webpack-merge 进行模块合并

    const config: Configuration = merge(commonPlugin, {...})

    未解决的问题

  • 关于 import 模块
  • 项目中保留了一份 webpack.common.js的文件,发现在 import 模块的时候 会先找到 这个.js的 而不是 .ts

    import commonPlugin from './webpack.common'
    

    ts.config 中有一个 allowJs 参数 如果设置为TRUE 则可以引入js文件 但是这个默认的是FALSE 所以应该不会有引入 js文件

    所以很奇怪 - 文档

    暂时将js文件名修改了

    <Banner once={::this.update} />
    

    这个主要是借助了bable 的 transform-function-bind 双冒号实现绑定

    TS不支持这种写法 可以调整为

    <Banner once={() => this.update} />
    <Channel clickOnce={this.clickOnce.bind(this)} />
    

    issue

    es6的新语法

    组件中有使用

    const result = Object.assign({}, params, info)
    

    1 借助lodash

    安装lodash.assign和@types/lodash

    2 更换复制对象方案

    3 调整tsconfig配置文件

    target: es5
    
    target: es6
    

    注意可能需要重启 VScode 才可以生效

    3 img 元素属性

    在获取img元素的src属性的时候,是这么写的

    (target as HTMLElement).getAttribute('src')
    

    然后在直接设置src值的时候

    (item as HTMLElement).src = itemSrc
    

    这样就会报错,需要调整为

    (item as HTMLImageElement).src = itemSrc
    

    getAttribute 属于 HTMLElement 属性,而 src 属于 HTMLImageElement 的属性

    补充一下 element HTMLElement node 的属性方法

    element对象

    htmlelement对象

    node对象

    后续还在调整中,继续更新掉坑记录部分

    行走的柯南 前端工程师 48.9k
    粉丝