简体   繁体   中英

TypeScript type checking on type rather than instance (part 2)

Part one asks the question - "Is it possible for TypeScript to ensure that a parameter is of a given type or its derivatives, rather than an instance of a type or its derivatives?"

TypeScript type checking on type rather than instance

The solution in part one is to use the typeof keyword

Example

function giveMeAType(type: typeof Foo): void {
}

or with generics

function giveMeAType<T extends typeof Foo>(type: T): void {
}

Expanding on this solution, I have a new problem when constructors are introduced to derived types

class Mangler<T> {
    protected constructor(
        public readonly item: T) {
    }

    public static getManglers(mangler: typeof Mangler): typeof Mangler[] {
        var whatever = [];
        return whatever;
    }
}

class StringMangler extends Mangler<string> {
    // No constructor override here...
}

class NumberMangler extends Mangler<number> {
    // But in this case, I need one...
    private constructor(
        public readonly item: number) {
        super(item);
    }
}

// This one works while StringMangler does not override the constructor.
Mangler.getManglers(StringMangler);

// But when I override the constructor, it doesn't work.
Mangler.getManglers(NumberMangler);

Playground

How then do me maintain Type checking with constructor overrides?

PS I want the derived types to have the ability to have private or protected constructors!

Update 1

To elaborate on Nitzan Tomer's answer, I can make the constructor protected , and the error goes away, but I can't make the constructor polymophic...

class NumberMangler extends Mangler<number> {
    // This polymorphic constructor doesn't work.
    public constructor(
        public readonly item: number,
        public readonly name: string) {
        super(item);
    }
}

If you make the NumberMangler.constructor protected then the error goes away:

class NumberMangler extends Mangler<number> {
    protected constructor(
        public readonly item: number) {
        super(item);
    }
}

Edit

This should work:

class NumberMangler extends Mangler<number> {
    protected constructor(item: number);
    protected constructor(item: number, name: string);
    protected constructor(
        public readonly item: number,
        public readonly name?: string) {
        super(item);
    }
}

You don't really need the non-implementation signatures, but I think it makes it more readable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM