typescript高級編程(二)

類型限制在數組裏面寫函數

export interface Plugin {
  extraReducers?: () => {
    [name: string]: (stare: any, ...payload: any) => void
  }
}

const plugins: Plugin[] = [
  {
    extraReducers() {
      return {
        reducers1(state: any, payload: any) {
        },
      };
    },
  },
  {
    extraReducers() {
      return {
        reducers2(state: any, payload: any) {
        },
      };
    },
  },
];
interface ExtraTwo {
  a: () => number
}

let b: ExtraTwo[] = [
  {
    a() {
      return 1;
    }
  },
  {
    a() {
      return 2;
    }
  }
];
for (let item of b) {
  item.a!();
}
我的理解!()是應該是語義化
interface ExtraTwo {
  a: (() => number) | number
}

let b: ExtraTwo[] = [
  {
    a() {
      return 1;
    }
  },
  {
    a: 0
  }
];

as const

typescript 3.4

angular7使用的ts3.1

angular9使用的ts3.7

不可變斷言

let foo = {
  name: "foo",
  contents: [1,2,3],
} as const;
foo.age=12;
// 報錯啦
interface Icon {
  x: number;
  y: number;
  name: 'we' | 'you' | 'hello' | undefined;
}
const myBeautifulIcon: Icon = Object.assign(
  {x: 2, y: 2},
  production ? {name: 'we' } : {name: 'you' as const}
);
報錯啦,因爲name不是確定的值
修改成
const myBeautifulIcon: Icon = Object.assign(
  {x: 2, y: 2},
  production ? {name: 'we' as const} : {name: 'you' as const}
);
就確定啦

接口

interface ClockInterface {
  currentTime: Date;

  setTime(d: Date): void
}
class Clock implements ClockInterface {
  currentTime = new Date();

  setTime(d: Date): void {
    this.currentTime = d;
  }
}
interface Handler<T, P, S> {
  type: T

  handle(payload: P): S
}

class Foos implements Handler<string, object, string> {
  constructor() {
  }

  type = 'sss';

  handle(payload: object): string {
    this.type = 'bbb';
    return this.type;
  }
}

Promise 類型限制

const test = (x: string): Promise<string> => Promise.resolve(x);

Recode 映射的高級用法

1
const arr: Record<string, () => void>[] = [
  {
    foo: () => {
    }
  },
  {
    broken: () => {
    }
  }
];

2
type Employee = () => number;
const add: Employee = () => 1;

3
type Variations = () => Record<string, () => void>[];

const arrMethod: Variations = () => [
  {
    foo: () => {
    }
  },
  {
    broken: () => {
    }
  }
];
type Key = 'a' | 'b' | 'c';

const index1: Record<Key, string> = {a: '', b: 'a', c: 'dd'}; 

遞歸類型

type SomeType = { type: 'zero' }
  | { type: 'one', hello: string, next: SomeType };

let mutable: SomeType = {
  type: 'one', hello: 'sss', next: {
    type: 'zero'
  }
};
let mutableOne: SomeType = {
  type: 'one', hello: 'aaa', next: {
    type: 'one', hello: 'aaa',
    next: {
      type: 'zero',
    }
  }
};

遇到的問題

type SomeType = { type : 'zero' }
              | { type : 'one', hello : string, next : SomeType };

let mutable : SomeType = { type : 'zero' };

switch( mutable.type ){
    case 'zero' :
        break;
    case 'one' : // error is here, says 'zero' is not comparable to 'one'
        break;
}

建議這麼改

type SomeType = { type: 'zero' }
  | { type: 'one', hello: string, next: SomeType };

let mutable = {type: 'zero'} as SomeType;
mutable = {type: 'one', hello: 's', next: {type: 'zero'}} as SomeType;
switch (mutable.type) {
  case 'zero' :
    break;
  case 'one' : 
    break;
}

unknown

typescript3.0

angular7 ts3.1

unknown 是 any 類型對應的安全類型

unknown 和 any 的主要區別是 unknow 類型會更加嚴格

let value:any;
console.log(value.foo.bar);

let value1:unknown;
console.log(value1.foo.bar);// 報錯啦

unknow 類型的主要價值: Typescript不允許我們對類型爲unknown的值執行任意操作,相反,我們執行某種類型以縮小值的類型範圍

const value1: any = 'aaa';
const value2: string = value1;

const value: unknown = "Hello World";
const someString: string = value;
// 報錯   Type 'unknown' is not assignable to type 'string'.
修改成
const value: unknown = "Hello World";
const someString: string = value as string;

但是也有一個問題

const value: unknown = 42;
const someString: string = value as string;
const otherString = someString.toUpperCase();  // 報錯了
> 這個會在運行時報錯

可以把參數當成類型執行判斷

type IsArray<T> = T extends unknown[] ? true : false;
const arr1: IsArray<string> = false;
// 可以當成參數參入進去
const arr2: IsArray<[1, 2, 3]> = true;
interface Dates {
  prop: number
}

type DatesOne<T> = () => T;
const add: DatesOne<Dates> = () => ({prop: 1});

關於類型合併的問題

// a對象 b字符串 c任意
const add1 = (a, b, c) => {
  return {...a, [b]: c}
}
// 添加限制
const add3 = (a: object, b: string, c: unknown) => {
  return {...a, [b]: c}
}
// 問題,我們無法寫返回的類型
//所以需要添加泛型,確認的入口的限制
function add2<TObject, TName extends string, TValue>(obj: TObject, name: TName, value: TValue) {
  return {...obj, [name]: value}
}
// 添加入口的限制
function add3<TShape, TName extends string, TValue>(
  obj: TShape, name: TName, value: TValue): TShape & { [name in TName]: TValue } {
  return {...obj, [name]: value};// 報錯啦
}
// 遇到這種情況,可能是typescript還不夠完整,暫時解決思路還是強大的斷言
function add3<TShape, TName extends string, TValue>(
  obj: TShape, name: TName, value: TValue) {
  return {...obj, [name]: value} as TShape & { [name in TName]: TValue } ;
}

提取出完整版

type TShape<T, N extends string, D> = (obj: T, name: N, value: D) => T & { [name in N]: D };
const add1: TShape<object, string, unknown> = (a, b, c) => {
  return {...a, [b]: c}
};
console.log(add1({name: 'xx'}, 'age', [1, 2, 3]));
// { name: 'xx', age: [ 1, 2, 3 ] }

源碼探索

lib.es2019.string

interface String{
    trimEnd():string;
    trimStart():string;
    trimLeft():string;
    trimRight():string;
}

學習

interface IntArrays {
  add(): number
}

const addMethods: IntArrays = {
  add() {
    return 1;
  }
};

function 在typescript不能被new

function Foo() {
  return 1;
}

let a = new Foo();// 報錯啦

官網說,這是ECMAscript的工作方式,我不想在代碼庫中使用,我們可以用class

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章