microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.23k stars 12.39k forks source link

Unable to get strong typing. #27230

Closed guptaamol closed 5 years ago

guptaamol commented 6 years ago

TypeScript Version: 3.1.0-dev.201xxxxx

Search Terms: typescript generics

Expected behavior: expecting strong typing. for variables { prop, payload } in reducer.

Actual behavior: unable to get strong typing.

Playground Link: http://www.typescriptlang.org/play/#src=type%20someType%20%3D%20%7B%0D%0A%20%20%20%20a%3A%20number%2C%0D%0A%20%20%20%20c%3A%20string%0D%0A%7D%0D%0A%0D%0Atype%20Action%3CT%20extends%20string%3E%20%3D%20%7B%20type%3A%20T%20%7D%3B%0D%0Atype%20ActionWithPayload%3CT%20extends%20string%2C%20P%3E%20%3D%20%7B%20payload%3A%20P%20%7D%20%26%20Action%3CT%3E%0D%0A%0D%0Aconst%20someTypeAction%20%3D%20'Some%20Type%20Action'%3B%0D%0A%0D%0Atype%20updatePropPayload%3CT%2C%20K%20extends%20keyof%20T%3E%20%3D%20%7B%20prop%3A%20K%2C%20value%3A%20T%5BK%5D%20%7D%0D%0A%0D%0Atype%20updateProp%3CU%2C%20V%20extends%20string%3E%20%3D%0D%0A%20%20%20%20%3CT%20extends%20U%2C%20K%20extends%20keyof%20T%3E(payload%3A%20updatePropPayload%3CT%2C%20K%3E)%20%3D%3E%0D%0A%20%20%20%20%20%20%20%20ActionWithPayload%3CV%2C%20updatePropPayload%3CT%2C%20K%3E%3E%0D%0A%0D%0Atype%20updatePropSomeType%3CV%20extends%20string%3E%20%3D%20updateProp%3CsomeType%2C%20V%3E%3B%0D%0A%0D%0Aconst%20someAction%3A%20updatePropSomeType%3Ctypeof%20someTypeAction%3E%20%3D%20(payload)%20%3D%3E%0D%0A%20%20%20%20(%7B%20type%3A%20someTypeAction%2C%20payload%20%7D)%3B%0D%0AsomeAction(%7B%20prop%3A%20'c'%2C%20value%3A%20'200'%20%7D)%3B%0D%0AsomeAction(%7B%20prop%3A%20'a'%2C%20value%3A%20200%20%7D)%0D%0A%0D%0Aexport%20const%20Actions%20%3D%20%7B%20someAction%20%7D%0D%0A%0D%0Atype%20FunctionType%20%3D%20(...args%3A%20any%5B%5D)%20%3D%3E%20any%3B%0D%0Atype%20ActionCreatorMapObject%20%3D%20%7B%20%5BactionCreator%3A%20string%5D%3A%20FunctionType%20%7D%3B%0D%0Atype%20ActionUnion%3CA%20extends%20ActionCreatorMapObject%3E%20%3D%20ReturnType%3CA%5Bkeyof%20A%5D%3E%3B%0D%0A%0D%0Atype%20Actions%20%3D%20ActionUnion%3Ctypeof%20Actions%3E%3B%0D%0A%0D%0Alet%20r%3A%20Actions%3B%0D%0Aswitch%20(r.type)%20%7B%0D%0A%20%20%20%20case%20'Some%20Type%20Action'%3A%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20%7B%20prop%2C%20value%20%7D%20%3D%20r.payload%3B%0D%0A%20%20%20%20%20%20%20%20break%3B%0D%0A%7D%0D%0A

ghost commented 5 years ago

This seems to be working for me in typescript@next. It's not clear what you expected to happen.

guptaamol commented 5 years ago

I was hoping prop and value in the scope for case statement 'Some Type Action' would be some sort of union.

In this case prop = 'a' | 'c' and value = 'string' | 'number';

Am i doing something wrong ?

ghost commented 5 years ago

I think the problem is when you get ReturnType of a generic function.

In this simple example:

type Cb<U> = <T extends U, K extends keyof T>() => K;
type Rt = ReturnType<Cb<{ x: number }>>;

T extends U, so it might have any set of keys. So Rt is string | number | symbol, AKA the type of any possible key. It works when you change to type Cb<T> = <K extends keyof T>() => K;.

The definition you gave for updateProp is:

type updateProp<U, V extends string> =
  <T extends U, K extends keyof T>(payload: updatePropPayload<T, K>) =>
      ActionWithPayload<V, updatePropPayload<T, K>>

It would work if you wrote:

type updateProp<T, V extends string> =
  <K extends keyof T>(payload: updatePropPayload<T, K>) =>
      ActionWithPayload<V, updatePropPayload<T, K>>
guptaamol commented 5 years ago

You're right, thanks mate. God Bless.

On Fri, Sep 21, 2018 at 9:32 PM Andy notifications@github.com wrote:

I think the problem is when you get ReturnType of a generic function.

In this simple example:

type Cb = <T extends U, K extends keyof T>() => K;type Rt = ReturnType<Cb<{ x: number }>>;

T extends U, so it might have any set of keys. So Rt is string | number | symbol, AKA the type of any possible key. It works when you change to type Cb = () => K;.

The definition you gave for updateProp is:

type updateProp<U, V extends string> = <T extends U, K extends keyof T>(payload: updatePropPayload<T, K>) => ActionWithPayload<V, updatePropPayload<T, K>>

It would work if you wrote:

type updateProp<T, V extends string> =

(payload: updatePropPayload) => ActionWithPayload> β€” You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub , or mute the thread .
typescript-bot commented 5 years ago

This issue has been marked as 'Question' and has seen no recent activity. It has been automatically closed for house-keeping purposes. If you're still waiting on a response, questions are usually better suited to stackoverflow.