简体   繁体   中英

Default value for default generic

Consider a generic class:

abstract class Base<T={}> {
    public getSmth(): T {
        ...
    }
}

I want getSmth method to return {} if T={} and be abstract (require to be overriden in derived classes) for all other T . Cow can I do that?

I've tried following code , but the problem is that there's no error for class C :

abstract class Base<T={}> {
    public getSmth(): T {
        return {} as T;
    }
}

class A extends Base<{}> {
    // No need to override `getSmth`
}

class B extends Base<{ x: number }> {
    public getSmth() { // Need to override as generic differes
        return {x: 8};
    }
}

class C extends Base<{ x: number }> {
    // No override for a generic parameter should be a error!
}

You can't have the method abstract for some values of T and not abstract for other values of T (even if the value is a default value for T ). A better solution would be to make the method abstract and have a default implementation for {} if this a common case. This also avoid type assertions in the method.

abstract class Base<T> {
    public abstract getSmth(): T;
}
abstract class EmptyBase extends Base<{}> { // Implementation for {}
    public getSmth(): {} {
        return {}
    }
}

class A extends EmptyBase {
    // No need to override `getSmth` 
}

class B extends Base<{ x: number }> {
    public getSmth() { // Need to override as generic differes
        return {x: 8};
    }
}

class C extends Base<{ x: number;}> { // Must override error if you don't
}

It's possible to use an additional interface, but in that case you'll need to specify it explicitely for every child class: playground

interface IBase<T={}> {
    getSmth(): T;
}

abstract class Base<T={}> {
    public getSmth() {
        return {};
    }
}

class A extends Base<{}> implements IBase<{}> {
    // No need to override `getSmth`
}

class B extends Base<{ x: number }> implements IBase<{ x: number }> {
    public getSmth() { // Need to override as generic differes
        return {x: 8};
    }
}

class C extends Base<{ x: number }> implements IBase<{ x: number }> {
    // No override for a generic parameter should be a error!
}

And there will be a error:

 Class 'C' incorrectly implements interface 'IBase<{ x: number; }>'. Types of property 'getSmth' are incompatible. Type '() => {}' is not assignable to type '() => { x: number; }'. Type '{}' is not assignable to type '{ x: number; }'. Property 'x' is missing in type '{}'. 

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