欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用typescript推導已有變量的盲盒類型詳情

 更新時間:2022年08月14日 10:06:21   作者:東東么么噠???????  
這篇文章主要介紹了使用typescript推導已有變量的盲盒類型詳情,文章圍繞主題展開詳細的內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下

遷移盲盒

當我們從JavaScript一鍵轉換Typescript的時候,any便是最省事的做法,對于維護并不友好(雖然能跑就行),同時每個變量對于我們來說都是盲盒,它到底是什么類型?

類型推導

基礎類型的推導

基礎數據類型的類型推導還是挺簡單的

let a = 1;
type A = typeof a; // number;

let b = '2'
type B = typeof b; // string;

let c;
type C = typeof c; // undefined;

一個typeof就可以把原始值類型推導出來了!

我們整理下基礎數據類型有哪些?

// 沒錯,7種數據類型
type Base = string | number | boolean | null | undefined | symbol | bigint;

對象的推導

這里我們來實現下普通對象如何推導

let obj = { a: 1, b: '2', c: true, d: null };
type Obj = typeof obj;
// { a: number; b: string; c: boolean; d: null; }

沒錯,也是這么簡單!

數組的推導

為什么上面的對象除開數組呢?因為數組在typescript比較特殊,既可以用元祖來聲明,又可以用數組來聲明

也可以說數組包含了元祖

type isContain = [1, 2] extends Array<number> ? true : false; // true

嘗試繼續(xù)通過typeof來實現推導

let arr = [1, '2', null, false];
type Arr = typeof arr; // (string | number | boolean | null)[]    ???
type Arr1 = typeof arr[0] // string | number | boolean | null    ???

好吧,得到的竟然是聯合類型數組,是不是和我們預期的不一樣?

我們定義一個數組,卻沒有聲明類型,對于數組來說,默認就是 Array,由于不斷填充了 number,string,null,boolean的值,最后變成了 Array<string | number | boolean | null>,而且是每一個元素都是聯合類型

重新整理下,我們需要的是啥?

[1, '2', null, false] -> [number, string, null, boolean]

我們要的是元祖 [number, string, null, boolean],而不是數組 Array<string | number | boolean | null>

整理下todo,我們需要的是:

  • 固定長度的數組類型
  • 每個元素都有獨立的類型
let arr = [1, '2', null, false] as const;
type Arr = typeof arr; // readonly [1, '2', null, false]
type Arr1 = typeof arr[0] // 1

第一個 todo 實現了,第二個有點像,但又不對,我們要的是數據類型,而不是某個具體的值

實現一個轉換類型的泛型

我們要的是 1 轉 number, 'A' 轉 string,只需要列出所有的基礎類型做轉換就可以了

type GetType<T> = T extends string ? string :
    T extends number ? number :
    T extends boolean? boolean :
    T extends null ? null :
    T extends undefined ? undefined :
    T extends symbol ? symbol :
    T extends bigint ? bigint : T;

type Arr1 = typeof arr[0] // number
type Arr2 = typeof arr[1] // string

那再遍歷一次元祖就可以實現整個數組的類型轉換了

type TransArr<T extends Array<unknown>,
    R extends unknown[] = []> = {
        'loop': TransArr<T,
            [...R,
                T extends Base ?
                    GetType<T[R['length']]>: T[R['length']]
            ]
        >,
        'result': R,
}[T['length'] extends R['length'] ? 'result': 'loop'];

let arr = [1, '2', null, false] as const;
type Arr = typeof arr;
type ArrType = TransArr<Arr>; // [number, string, null, boolean]

函數的推導

函數的推導其實沒有必要,為什么這么說,函數參數和值類型不可控,除個別操作符或者明確類型

如 (a, b) => a * b ,返回值一定是number

如 (a) => Promise.resolve(a),返回值一定是Promise

let fn1 = (a, b) => a * b;
type Fn1 = typeof fn1; // (a: any, b: any) => number

function fn2(a) {
    return Promise.resolve(a);
}
type Fn2 = typeof fn2; // (a: any) => Promise<any>

大多是函數經過typeof后得到的結果是

(a: any, b: any, ...) => any;

這個類型可以限定參數數量更多的函數

function fn3(a, b, c) {
    return a + b + c;
}
function fn4(d) {
    return d + 1;
}
type Fn3 = typeof fn3; // (a: any, b: any, c: any) => any
type Fn4 = typeof fn4; // (d: any) => any

type F3_4 = Fn3 extends Fn4 ? true : false; // false
type F4_3 = Fn4 extends Fn3 ? true : false; // true

也就是說,參數多的函數總是包含了參數少的函數

根據上面的判斷,我們可以通過這個來實現函數的判斷

type isFunc<T> = (() => any) extends T ? true : false;

完善推導

  • 基礎類型直接返回類型
  • 數組用TransArr泛型轉一次
  • 函數直接返回typeof的值
  • 遍歷對象則用keyof實現
type Trans<T> = T extends Base
    ? GetType<T> : T extends Array<unknown>
    ? TransArr<T> : isFunc<T> extends true
    ? T : {
        [key in keyof T]: T[key] extends Base
            ? GetType<T[key]> : T[key] extends Array<unknown>
            ? TransArr<T[key]> : Trans<T[key]>;
        };

測試

let a1 = 1;
type test1 = Trans<typeof a1>; // number
let a2 = '2';
type test2 = Trans<typeof a2>; // string
let a3 = [1, '2', true, '3', 4] as const;
type test3 = TransArr<typeof a3>;
// [number, string, boolean, string, number]
let a4 = {
    a: 1,
    b: true,
    c: {
        a: 1,
        b: [1, '2']
    },
    d: [true, null]
} as const;
type test4 = Trans<typeof a4>;
// {
//     readonly a: number;
//     readonly b: boolean;
//     readonly c: {
//         readonly a: number;
//         readonly b: readonly [number, string];
//     };
//     readonly d: readonly [boolean, null];
// }
let a5 = {
    a: [
        {
            b: [
                { c: 1 }
            ]
        }
    ]
} as const;
type test5 = Trans<typeof a5>;
// {
//     readonly a: readonly [{
//         readonly b: readonly [{
//             readonly c: number;
//         }];
//     }];
// }
let a6 = (a, b, c) => a + b + c;
type test6 = Trans<typeof a6>;
// (a: any, b: any, c: any) => any
let a7 = [
    function fn() {
        return 1;
    },
    (a, b) => a * b,
    (a) => Promise.resolve(a)
] as const;
type test7 = TransArr<typeof a7>;
// [() => number, (a: any, b: any) => number, (a: any) => Promise<any>]
let a8 = {
    a: 1,
    b: [true, null],
    c: [() => void, (a, b) => a],
    d: {
        e: [
            (a, b) => null,
            {
                f: [1]
            }
        ]
    }
} as const;
type test8 = Trans<typeof a8>;
// {
//     readonly a: number;
//     readonly b: readonly [boolean, null];
//     readonly c: readonly [() => undefined, (a: any, b: any) => any];
//     readonly d: {
//         readonly e: readonly [(a: any, b: any) => null, {
//             readonly f: readonly [number];
//         }];
//     };
// }

到此這篇關于使用typescript推導已有變量的盲盒類型詳情的文章就介紹到這了,更多相關typescript盲盒類型內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論