typescript 泛型类型不与父类一起工作

xqkwcwgp  于 2023-04-22  发布在  TypeScript
关注(0)|答案(1)|浏览(151)

这里的任何打字Maven都可以查看这段代码,并指导我这里有什么问题?
我有一个ParentSchema,它保存了DB中的公共字段。因此其他模式可以扩展ParentSchema
我还有一个ModelService类,它包含常见的DB函数(例如:update). ModelService接受Model作为泛型类型。
还有另一个MongoJob类,我将传递给ModelService函数,并提供所需的详细信息。ModelService的相同泛型类型也从ModelService.update()函数传递给MongoJob

/* ParentSchema to hold common properties */
export class ParentSchema {
    id!: string;
}

/* MongoJob to hold properties to run job */
export interface MongoJob<T extends ParentSchema> {
    /**
     * primary key value of the model
     */
    id?: number | string;
    /**
     * body object used for create or update
     */
    body?: Partial<T>;
}
export class MongoJob<T extends ParentSchema> {
    constructor(job: MongoJob<T>) {
        this.id = job.id;
        this.body = job.body || {};
    }
}

/* ModelService to hold common methods */
export class ModelService<M extends ParentSchema> {

    constructor() { }

    async update(job: MongoJob<M>): Promise<any> {
        try {
            console.log(job);
            const response = {}; // call db functions
            return response;
        } catch (error) {
            return { error };
        }
    }
}

/* Country model */
export class Country extends ParentSchema {
    name!: string;
}

/* Calling functions using Country model */
const service = new ModelService<Country>();

/* Working */
service.update(
    new MongoJob<Country>({
        id: 1,
        body: {
            name: 'Demo'
        },
    })
);

/* Working */
service.update(
    new MongoJob({
        id: 1,
        body: {},
    })
);

/* Not Working */
service.update(
    new MongoJob({
        id: 1,
        body: {
            name: 'Demo'
        }, // Type '{ name: string; }' is not assignable to type 'Partial<ParentSchema>'.
    })
);

当body不为空并且没有将<Country>作为泛型类型传递时,new MongoJob()不工作,<Country>已经传入new ModelService()
TSPlayground

jjjwad0x

jjjwad0x1#

当您在没有泛型的情况下调用new MongoJob( ... )时,您将获得默认的泛型值,即ParentSchema,这是因为您在类声明(class MongoJob<T extends ParentSchema>)中使用了泛型约束。
这一点:

foo.bar(new Baz());

与此类似:

const baz = new Baz();
foo.bar(baz);

这并不是说它在内联示例化时将new Baz()视为变量,而是示例本身是独立于传递给它的方法而创建的:在这种情况下没有上下文类型推断的机会。
这与声明一个对象字面量不同,后者会获得类型推断。一个选择是在方法中创建示例:

class Foo<T> {
  bar(obj: T) {
    const baz = new Baz<T>(obj);
    // ...
  }
}

// Expected type inference will work here: 
foo.bar({ fizz: 'buzz' });

在文档中阅读更多关于类型推断的内容。

相关问题