繁体   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