简体   繁体   English

返回推断的泛型类型

[英]Return inferred generic type

I want to return the inferred type from a function on a class, but the return type is of the extended generic type, not the actual result of the function.我想从类上的函数返回推断类型,但返回类型是扩展泛型类型,而不是函数的实际结果。 I want to instead return the inferred type of the function.我想返回函数的推断类型。

I tried a few things surrounding wrapping and unwrapping, but was unable to get those to work.我尝试了一些围绕包装和展开的方法,但无法让它们正常工作。

Problem : newDocumentSet is of type IDocumentSet<DocumentTypes, IContact, never> , not the type returned in the create functions extend parameter问题newDocumentSet的类型是IDocumentSet<DocumentTypes, IContact, never> ,而不是创建函数扩展参数中返回的类型

Notes : I would like the create function to return the extended instance, not the interface of IDocumentSet .注意:我希望 create 函数返回扩展实例,而不是IDocumentSet的接口。 It seems like this bit (create<TExtension extends IDocumentSet<TDocumentType, TEntity, TExtraExclusions>>) is screwing it up, I am just not sure how to enforce a return type that extends IDocumentSet<TDocumentType, TEntity, TExtraExclusions> yet returns the extended type not IDocumentSet<TDocumentType, TEntity, TExtraExclusions> .似乎这个位 (create<TExtension extends IDocumentSet<TDocumentType, TEntity, TExtraExclusions>>) 搞砸了,我只是不确定如何强制执行扩展IDocumentSet<TDocumentType, TEntity, TExtraExclusions>的返回类型但返回扩展类型不是IDocumentSet<TDocumentType, TEntity, TExtraExclusions>

Goal : I want to create the ability to return the extended class from the create function, not the interface.目标:我想创建从创建函数返回扩展类的能力,而不是接口。

Example is below and here in this fiddle示例在下面,在这个小提琴中

Shorter Example 更短的例子

I also found this post about wrapping and unwrapping, but was unable to get it to work for my needs我还发现了这篇关于包装和展开的帖子,但无法满足我的需要

This example is from a larger code base, code surrounding TExtraExclusions has been omitted to keep this example smaller, yet the generics remain.此示例来自更大的代码库,已省略围绕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";
        }
    }
});

In your shorter example, you are using the instantiation expression typeof DocumentSet<TDocumentType, TEntity> to refer to the type of a generic class constructor whose generic type parameters have been specified with the arguments TDocumentType, TEntity .在您较短的示例中,您使用实例化表达式typeof DocumentSet<TDocumentType, TEntity>来引用泛型类构造函数的类型,其泛型类型参数已使用参数TDocumentType, TEntity指定。 That is, a type essentially the same as new() => DocumentSet<TDocumentType, TEntity> (using a construct signature ).也就是说,与new() => DocumentSet<TDocumentType, TEntity>基本相同的类型(使用构造签名)。

If you replace the instantiation expression with the equivalent type:如果将实例化表达式替换为等效类型:

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

Then you get the expected inference when you call extend() :然后,当您调用extend()时,您会得到预期的推断:

myNewSet.someNewFunction(); // okay

I'm not sure why it doesn't work the way you wrote it.我不确定为什么它不像你写的那样工作。 Instantiation expressions are new (they were introduced in TypeScript 4.7 which is the latest release version), so I can't tell if this inference failure is a language bug, or a design limitation, or the intentional behavior.实例化表达式是新的(它们是在最新版本的 TypeScript 4.7 中引入的),所以我无法判断这种推理失败是语言错误、设计限制还是故意行为。 If it matters, someone might want to open an issue in GitHub asking about it.如果这很重要,有人可能想在 GitHub 中打开一个问题来询问它。 If that happens and we get an answer, we can update this post.如果发生这种情况并且我们得到了答案,我们可以更新这篇文章。

Playground link to code Playground 代码链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 TypeScript 具有推断返回类型的通用 function - TypeScript generic function with inferred return type 如何修复通用 TypeScript function 以返回有效的推断类型? - How to fix generic TypeScript function to return valid inferred type? 使用推断方法返回类型的Typescript泛型约束 - Typescript generic constraint that uses inferred method return type 默认回调返回类型与应该被推断为该返回类型的泛型类型冲突 - Default callback return type conflicts with generic type which should be inferred as that return type 在 React 组件上推断通用类型 - Inferred Generic Type on React Component 未推断的扩展接口的通用类型 - Generic type of extended interface not inferred 如何创建一个泛型 typescript 类型 function 并从参数类型推断出返回类型? - How do I make a generic typescript type function that has the return type inferred from the argument type? 为什么泛型类型参数 T 在返回类型中是“未知的”? 如何键入此 function 以便正确推断返回类型? - Why is the generic type parameter T “unknown” in the return type? How can I type this function so that the return type is correctly inferred? 打字稿:一般类型被推断为文字类型 - Typescript: Generic Type being inferred to Literal Type TypeScript 泛型类型参数是通过函数推断出来的,而不是类型? - TypeScript generic type parameters are inferred with functions, but not type?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM