Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default method generic doesn't apply from class generic #20505

Closed
cajoy opened this issue Dec 6, 2017 · 7 comments
Closed

Default method generic doesn't apply from class generic #20505

cajoy opened this issue Dec 6, 2017 · 7 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@cajoy
Copy link

cajoy commented Dec 6, 2017

Code

class TestClass<T_MODEL = any> {
    create<T_DATA = T_MODEL>(data: T_DATA) {
        // todo
    }
}

const testString = new TestClass<string>()

testString.create(1) // Ok, but should be error
testString.create<number>(1) // Ok

const testNumber = new TestClass<number>()

testNumber.create(1) // Ok

Expected behavior:

By method default generic should use generic from the class

Actual behavior:

while it ignores default value: create<T_DATA = T_MODEL> and applies any

@ghost
Copy link

ghost commented Dec 6, 2017

A default for a type parameter in a function only applies if a type can't be inferred. (Note that it's not using any, it's using number, which can be inferred from the argument.) If you want T_DATA to always be T_MODEL, just replace it with that to have a non-generic signature.

@cajoy
Copy link
Author

cajoy commented Dec 6, 2017

I am building REST api layer.. but data could be different and response could be different for the same method.

So what I want is to define default type of request and type of response.

But sometimes there is a need of overwriting it... I can create custom method to handle it but thought I can do it just with generics as everything else is the same

@ghost
Copy link

ghost commented Dec 6, 2017

So, you want a parameter that's not T_MODEL to be allowed, but only if the user supplies an explicit type argument? I don't think that's something we support; you can just add a second method createWithUnusualData like you said, or just allow any data in the original method.

@cajoy
Copy link
Author

cajoy commented Dec 6, 2017

I see.. basically it is not possible right now,

here is my definitions to illustrate what I mean:

export declare class RestApi<T_MODEL = any, T_MODEL_LIST = T_MODEL[]> extends Api {
    create<T_RESPONSE = T_MODEL, T_REQUEST = T_MODEL>(data: T_REQUEST, options?: any): Promise<T_RESPONSE>;
    update<T_RESPONSE = T_MODEL, T_REQUEST = T_MODEL>(id: number | string, data: T_REQUEST, options?: any): Promise<T_RESPONSE>;
    findById<T_RESPONSE = T_MODEL>(id: string | number, options?: any): Promise<T_RESPONSE>;
    findAll<T_RESPONSE = T_MODEL_LIST>(options?: any): Promise<T_RESPONSE>;
    find<T_RESPONSE = T_MODEL_LIST>(params: Object, options?: any): Promise<T_RESPONSE>;
    updateAttributes<T_RESPONSE = T_MODEL, T_REQUEST = T_MODEL>(id: number | string, data: T_REQUEST, options?: any): Promise<T_RESPONSE>;
    destroy<T_RESPONSE = T_MODEL>(id: number | string, options?: any): Promise<T_RESPONSE>;
}

So I define instance like

const api = new RestApi<string>()

then I can do type-checking like:

api.create('string') //ok
api.create(11) // also ok, while shouldn't be
api.create<number>(11) // also ok but no type-checking as I understand

@ghost
Copy link

ghost commented Dec 6, 2017

There's still type-checking even if you provide explicit type arguments. So api.create<number>("") would fail. The only difference explicit type arguments make is that we don't bother with type inference.

@mhegazy
Copy link
Contributor

mhegazy commented Jan 30, 2018

If you want to do both, verify an upper bound, and set a default, use extends T = T.. e.g.:

class TestClass<T_MODEL = any> {
    create<T_DATA extends T_MODEL = T_MODEL>(data: T_DATA) {
        // todo
    }
}

this will give an error on both:

testString.create(1) ;
testString.create<number>(1);

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Jan 30, 2018
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants