簡體   English   中英

返回推斷的泛型類型

[英]Return inferred generic type

我想從類上的函數返回推斷類型,但返回類型是擴展泛型類型,而不是函數的實際結果。 我想返回函數的推斷類型。

我嘗試了一些圍繞包裝和展開的方法,但無法讓它們正常工作。

問題newDocumentSet的類型是IDocumentSet<DocumentTypes, IContact, never> ,而不是創建函數擴展參數中返回的類型

注意:我希望 create 函數返回擴展實例,而不是IDocumentSet的接口。 似乎這個位 (create<TExtension extends IDocumentSet<TDocumentType, TEntity, TExtraExclusions>>) 搞砸了,我只是不確定如何強制執行擴展IDocumentSet<TDocumentType, TEntity, TExtraExclusions>的返回類型但返回擴展類型不是IDocumentSet<TDocumentType, TEntity, TExtraExclusions>

目標:我想創建從創建函數返回擴展類的能力,而不是接口。

示例在下面,在這個小提琴中

更短的例子

我還發現了這篇關於包裝和展開的帖子,但無法滿足我的需要

此示例來自更大的代碼庫,已省略圍繞TExtraExclusions的代碼以使此示例更小,但仍保留泛型。


export interface IDocumentSetBase<TDocumentType extends string> {

    get DocumentType(): TDocumentType;

    empty(): Promise<void>;
}

interface IDocumentSet<TDocumentType extends string, TEntity extends IDbRecord<TDocumentType>, TExtraExclusions extends (keyof TEntity) = never> extends IDocumentSetBase<TDocumentType> {
    info(): boolean
}

interface IDbRecord<TDocumentType> extends IDbAdditionRecord<TDocumentType> {
    readonly _id: string;
    readonly _rev: string;
}

interface IDbAdditionRecord<T> {
    readonly DocumentType: T;
}

export class DocumentSet<TDocumentType extends string, TEntity extends IDbRecord<TDocumentType>, TExtraExclusions extends (keyof TEntity) = never> implements IDocumentSet<TDocumentType, TEntity, TExtraExclusions> {

    private _documentType: TDocumentType;

    get DocumentType() { return this._documentType; }

    constructor(documentType: TDocumentType) {
        this._documentType = documentType;
    }

    info() {
        return true;
    }

    async empty() {

    }
}

class Builder<TDocumentType extends string, TEntity extends IDbRecord<TDocumentType>, TExtraExclusions extends (keyof TEntity) = never> {

    private _documentType: TDocumentType;

    constructor(documentType: TDocumentType) {
        this._documentType = documentType;
    }

    create<TExtension extends IDocumentSet<TDocumentType, TEntity, TExtraExclusions>>(extend: (Instance: typeof DocumentSet<TDocumentType, TEntity, TExtraExclusions>, documentType: TDocumentType) => TExtension = w => (w as any) as TExtension) {

        const result = extend(DocumentSet<TDocumentType, TEntity, TExtraExclusions>, this._documentType);

        return result;
    }
}

enum DocumentTypes {
    Contacts = "Contacts"
}

interface IContact extends IDbRecord<DocumentTypes> {
    firstName: string;
    lastName: string;
    address: string;
    phone: string;
}

const builder = new Builder<DocumentTypes, IContact>(DocumentTypes.Contacts);

const newDocumentSet = builder.create((Instance, documentType) => {
    return new class extends Instance {
        constructor() {
            super(documentType)
        }

        test() {
            return "some value";
        }
    }
});

在您較短的示例中,您使用實例化表達式typeof DocumentSet<TDocumentType, TEntity>來引用泛型類構造函數的類型,其泛型類型參數已使用參數TDocumentType, TEntity指定。 也就是說,與new() => DocumentSet<TDocumentType, TEntity>基本相同的類型(使用構造簽名)。

如果將實例化表達式替換為等效類型:

create<TExtension extends IDocumentSet<TDocumentType, TEntity>>(
    extend: (Instance: new () => DocumentSet<TDocumentType, TEntity>
    ) => TExtension = w => (w as any) as TExtension) {
    return extend(DocumentSet);
}

然后,當您調用extend()時,您會得到預期的推斷:

myNewSet.someNewFunction(); // okay

我不確定為什么它不像你寫的那樣工作。 實例化表達式是新的(它們是在最新版本的 TypeScript 4.7 中引入的),所以我無法判斷這種推理失敗是語言錯誤、設計限制還是故意行為。 如果這很重要,有人可能想在 GitHub 中打開一個問題來詢問它。 如果發生這種情況並且我們得到了答案,我們可以更新這篇文章。

Playground 代碼鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM