typescript - Bu genel tipin içindeki bir özellik için, bir genel arayüz içinde bir tipi nasıl tanımlarsınız


Örnek :

export interface Column<T> {
    field: string;
    columnFormatter?: (props: {
        value: any/** field type inside T**/; data: T; node: any
    }) => void;
}

field, T türü içindeki özelliğin adıdır, değerin o türde olduğunu nasıl söyleyebilirim?

export interface IPurchase {
    id: string;
    name: string;
    purchaseDate: Date;
}

let doSomethingWithMyDate: (myDate: Date) => (true);


const columns: Array<Column<IPurchase>> = [
    {
        field: "purchaseDate", /* "purchaseDate" must be inside IPurchase */
        columnFormatter: ({ value /* must identify that this is a Date */ }) => 
            doSomethingWithMyDate(value)

    }];

Cevap #1

columnFormatter parametresine ait props nesnesinin value özelliğinin türü ile field özelliği arasındaki ilişkiyi temsil etmek için, Column<T>’in T’nin her anahtarı için bir üyesi olan birleşim türü olması gerekir. Örneğin, verdiğiniz IPurchase örneğinde, Column<IPurchase>’in olması gerekir

type ColumnIPurchase = {
    field: "id";
    columnFormatter?: ((props: {
        value: string;
        data: IPurchase;
        node: any;
    }) => void);
} | {
    field: "name";
    columnFormatter?: ((props: {
        value: string;
        data: IPurchase;
        node: any;
    }) => void) 
} | {
    field: "purchaseDate";
    columnFormatter?: ((props: {
        value: Date;
        data: IPurchase;
        node: any;
    }) => void);
}

Bu, istediğiniz gibi davranacaktır:

const columns: Array<Column<IPurchase>> = [
    {
        field: "purchaseDate",
        columnFormatter: ({ value }) => doSomethingWithMyDate(value)
    },
    {
        field: "name",
        columnFormatter: ({ value }) => doSomethingWithMyDate(value) // error!
        //  string isn't a Date ----------------------------> ~~~~~ 
    }
];

Yani istediğimiz bu... bunu yapmak için Column<T> nasıl yazabiliriz?


İşte bir yol:

type Column<T> = { [K in keyof T]-?: {
    field: K;
    columnFormatter?: (props: { value: T[K]; data: T; node: any }) => void;
} }[keyof T]

Bu türün genel biçimi, {[K in keyof T]-?: F<K>}[keyof T], microsoft/TypeScript#47109'da ortaya konduğu gibi bir dağıtıcı nesne türü olarak bilinir; keyof T içindeki anahtarlar üzerinde bir eşlenen tür oluşturuyoruz ve ardından her anahtar K için F<K> birleşimini elde etmek amacıyla hemen keyof T ile ona indeksleme yapıyoruz.

Özellikle burada, K anahtarın türü ve T[K] bu anahtara karşılık gelen özellik değerinin türü olmak üzere, { field: K; columnFormatter?: (props: { value: T[K]; data: T; node: any }) => void; } öğesini hesaplıyoruz.

Ve Column<IPurchase>'in tam olarak istenen tipe değerlendiğini doğrulayabilirsiniz.

Koda yönelik oyun alanı bağlantısı