Microsoft/TypeScript

Mixin / Inheritance problem with Typescript - string not assignable to string|number|symbol

Open

#52,907 创建于 2023年2月22日

在 GitHub 查看
 (0 评论) (0 反应) (0 负责人)TypeScript (6,726 fork)batch import
BugDomain: classesHelp Wanted

仓库指标

Star
 (48,455 star)
PR 合并指标
 (平均合并 6天 17小时) (30 天内合并 9 个 PR)

描述

Bug Report

I have a typescript class. I'd like to subclass it and add a mixin. However, it keeps telling me that string not assignable to string|number|symbol. I don't understand why because the method signatures are the same.

🔎 Search Terms

typescript mixin prototype

🕗 Version & Regression Information

4.9.5

I just started using Typescript, so 4.9.5 is the version I was using since I started seeing it.

⏯ Playground Link

this shows the problem with UserRecord

this shows the way to work around the problem

💻 Code

This is as short as I can make the example and still show what's happening:

type TModel = {
    'User' : {
        username : string,
        password : string  | undefined,
    },
    'APIKey' : {
        privateKey: string,
    }
};
type TProps<T extends keyof TModel> = Partial<TModel[T]>;

type Constructor<T = {}> = new (...args: any[]) => T;

 class VingRecord<T extends keyof TModel> {
    constructor( private props: TProps<T>) { }

    public set<K extends keyof TProps<T>>(_key: K) {}
}

function RoleMixin<T extends Constructor>(Base: T) {
    return class RoleMixin extends Base {  };
}

class UserRecord extends RoleMixin(VingRecord<'User'>) {
    public set<K extends keyof TProps<'User'>>(_key: K) {}
}

and if you replace the RoleMixin with this it hides the problem with the funky prototype:

function RoleMixin<T extends IConstructable>(Base: T) {
    class RoleMixin extends Base {};
    return RoleMixin as {
        new (...args: any): RoleMixin;
        prototype: any;
    } & T;
}

🙁 Actual behavior

The code works, but typescript has a problem with the mixin thinking the type on VingRecord is any rather than 'User'. So it reports a type mismatch on the UserRecord.

More detail here with the guys who spotted the behavior

🙂 Expected behavior

I should be able to do the inheritance as shown in the code sample above without having to do the funky return from the mixin.

贡献者指南