typescript + react 項目開發體驗之typescript

目錄

前言

文檔太無趣,咱們就來說個故事嘗試着貫穿ts的知識點吧。node

part1-講個故事

從前有座山,山裏有座廟,聽說還有隻大腦腐,還有一些其餘什麼的react

interface IMountain{
    temple: Temple // 寺廟
    tiger?: Tiger // 腦腐
    [other: string]: any // 有點其餘什麼的
}
複製代碼

廟裏有個老方丈和不少個小和尚,養了一些雞啊鴨啊(就不說還有其餘什麼的)webpack

interface ITemple {
	holder: Holder // 老住持
    monk: Monck[] // 小和尚
    poultry: (ChickeC | Duck)[] // 雞鴨
}
複製代碼

描述完了以後咱們開始實現web

// 腦腐、鴨子、雞、人都屬於動物,咱們建個虛擬基類,不讓他實例化。
abstract class Animal{
  mouse = 1 // 一張嘴
  leg = 2 // 兩條腿
  protected voice(content:string){ console.log(content) }
}
// 鴨子是呱呱叫
class Duck extends Animal{
  quack(){ this.voice('quack') }
}
// 雞是咯咯噠
class Chicke extends Animal{
  crow(){ this.voice('gegeda') }
}
// 腦腐是嗷嗚並且是四條腿
class Tiger extends Animal{
  leg = 4
  howl(){ this.voice('howl') }
}
複製代碼

我靈機一動想讓他變成一隻強雞建議閱讀順序一、二、三、4typescript

// 三、定義一個構造函數類型,一下二者均可以
type ConstructorFuc<T> = new (...arg:any[])=>T;
interface IConstructorFuc<T>{
  new (...arg:any[]):T;
}

// 四、這個是雞特有的屬性
interface IChicke{
  crow():void
};
// 二、構建這個裝飾器,裝飾器接收一個構造函數做爲方法,定義返回類型是雞。
const strong = (ctor:ConstructorFuc<Animal & IChicke>)=>{
  return class extends ctor{
    crow(){
      super.crow();
      super.crow();
    }
  }
}
// 一、這裏用裝飾器增強雞
@strong
class Chicke extends Animal{
  crow(){ this.voice('gegeda') }
}
複製代碼

下面咱們來讓他展現下本身吧模塊化

const tiger = new Tiger();
tiger.howl()// howl
const duck = new Duck();
duck.quack()// quack
const chicke = new Chicke();
chicke.crow();// gegeda gegeda
複製代碼

能夠看到雞比較牛皮,叫了兩聲。函數

下面咱們來建立人物,給他多添加姓名這個屬性,發出聲音的方式就是speak了。post

interface IPeople{
  name: string
  speak(content: string):void
}
複製代碼

接下來是小和尚,小和尚不免會有個小祕密,通常不會輕易被人知道,可是總得有讓人知道的方法。ui

class Monck extends AbsAnimal{
  name: string;
  private secret = '講出本身的小祕密';
  speackSecret(){
    this.speak(this.secret);
  }
  constructor(param: Pick<IPeople, 'name'>){
    super();
    this.name = param.name;
  }
  speak(content:string){
    super.voice(`${this.name}:${content}`)
  }
}
複製代碼

衆所周知,住持同窗須要由小和尚成長而來,做爲住持同窗,能夠命令小和尚作本身能完成的事情,並且本身的名稱上冠上一個title。this

class Holder extends Monck{
  constructor(param: Pick<IPeople, 'name'>){
    super(param);
    this.name = param.name+`(住持)`;
  }
  command(monck:Monck, something: keyof Monck){
    if(typeof monck[something] === 'function'){
      console.log(`${this.name} 命令 ${monck.name} 去幹 ${something}`);
      (monck[something] as Function)();
    }
    console.log(`${monck.name} 幹不了 ${something}`);
  }
}
複製代碼

接下來,方丈同窗要求小和尚說出本身的祕密

const holder = new Holder({ name: '鳩摩智' });
const monck = new Monck({ name: '虛竹'});

holder.command(monck, 'speackSecret');
// 鳩摩智(住持) 命令 虛竹 去幹 speackSecret
// 虛竹:講出本身的小祕密
複製代碼

咱們讓他們都住進寺廟裏

const temple:ITemple = {
  holder,
  monks:[monk],
  poultry: [duck, chicke]
}
複製代碼

寺廟放進山裏,並有一隻來去自如的腦腐

const isTigerMountain = (mountain: IMountain)=>{
  console.log(`這${mountain.tiger ? '是' : '不是'}一座腦腐山`)
}
const mountain: IMountain = {
  temple
}
isTigerMountain(mountain);
mountain.tiger = tiger;
isTigerMountain(mountain);
Array().fill(6).forEach(data=>{
  (mountain.tiger as Tiger).howl()// aowu * 6
})
mountain.tiger = undefined;
isTigerMountain(mountain);
複製代碼

part2-d.ts文件

d.tsdeclare文件,定義文件,裏面內容只能包含一些定義,主要用法有如下。

  1. 聲明單個 js 文件

當 ts 須要引入 js 相關文件時,好比我有一個js文件,引入會報錯

// speak.js
export const leeSpeak = (word)=>{
  console.log(word);
};
// other.js
import speck from './speak';// Could not find a declaration file for module './speak'.
speck.leeSpeak();
複製代碼

解決方式是在speck.js同級目錄下新建一個同名的d.ts文件:

// speck.js
export const leeSpeak: (word:string)=>void;
複製代碼

這種方式有個問題就是,在運行 tsc 時,js文件不會導出到dist相關目錄( 在webpack下不要緊 )。

固然你也能夠啓動 allowjs,可是不要開checkjs,由於js沒法進行類型定義,而checkjs會按照ts進行語法檢查,若是正常的js語法不能被編譯器推斷容易產生報錯。

  1. 全局聲明變量 / 類型

編碼過程當中我們可能經過一、 webpack 的 externals屬性 或者 webpackDllPlugin 引入一些包;二、 DefinePlugin 定義一些變量;三、node_module 中 @types 文件夾下沒有相應生命文件包;爲了讓他們可以正常使用,咱們須要定義相應的類型。

// webpack.base.js
new DefinePlugin({
  "CURRENT_ENV": 'test'
})

// xx.d.ts
declare namespace lee{
    const name: string
}
declare module 'zhang'{
    const name: string
}
declare const CURRENT_ENV : 'test'
// xx.js
import zhang from 'zhang';
zhang.name
lee.name
CURRENT_ENV

複製代碼

全局包聲明不能使用 export、import 進行模塊引入和導出。

ps: 我們編碼的過程當中我們還會遇到一種狀況,就是 node_modules @types 下有相應的模塊化聲明文件,可是咱們想置於全局,舉例react。

// 一般狀況下使用react
// 可是全部頁面都引入難免有些麻煩
import React from 'react';


// global.d.ts
declare global{
    const React: typeof import("react");
}
export {}
複製代碼

typescript的一些常見問題就說到這裏啦。

相關文章
相關標籤/搜索