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

After updating to 3.x.x getting TS2536 #28647

Closed
pikax opened this issue Nov 22, 2018 · 10 comments
Closed

After updating to 3.x.x getting TS2536 #28647

pikax opened this issue Nov 22, 2018 · 10 comments
Assignees
Labels
Breaking Change Would introduce errors in existing code Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@pikax
Copy link

pikax commented Nov 22, 2018

TypeScript Version: [email protected]

Search Terms:
TS2536 Record Map vuex

Code

interface ITest {
  expectedStr: string;
  expectedN: number;
}

interface MapAccessor<Getters> {
  <T = Getters, Map extends Record<string, keyof T> = Record<string, keyof T>>(
    map: Map
  ): { [K in keyof Map]: (() => T[Map[K]]) };
}

interface TestAccess {
  str: "expectedStr";
}

const t: MapAccessor<ITest> = {} as any;

const str = t({
  str: "expectedStr"
}).str;

Expected behavior:
No compile issue, is working using [email protected], checked the breaking changes and found nothing in regards to this.

Intellisense still works as expected giving error if you change expectedStr to an invalid value.

Actual behavior:
Not giving error: index.ts:9:33 - error TS2536: Type 'Map[K]' cannot be used to index type 'T'.

Playground Link:
playground

@jack-williams
Copy link
Collaborator

This might be affected by this: #27490 (and thus working as intended).

Map[K] is no longer pulling in the constraint keyof T because both Map and K are generic.

I'd wait on a final say from someone on the team though,

@pikax
Copy link
Author

pikax commented Nov 23, 2018

What I find odd is the intellisense/editor picking up the correct value.

Is there a way to have the same behavior without the error?

@jack-williams
Copy link
Collaborator

Is your editor using an older version of tsserver?

@pikax
Copy link
Author

pikax commented Nov 23, 2018

I'm using VSCode and even the typescript playground it works (even with the error it resolves the correct type).

image

playground

EDIT:
image

@weswigham weswigham added Needs Investigation This issue needs a team member to investigate its status. Domain: Indexed Access Types The issue relates to accessing subtypes via index access labels Nov 26, 2018
@weswigham
Copy link
Member

I think @jack-williams is right; but I'm unsure if we wanted this specific kind of pattern to break

@ahejlsberg
Copy link
Member

This is working as intended. A simplified example:

function f1<T, U extends Record<string, keyof T>, K extends keyof U>(obj: T, map: U, key: K) {
    return obj[map[key]];  // Error
}

Here, U is constrained to an object type where properties with string names are constrained to keyof T. However, it is possible for an instantiation to supply a type argument for U that has properties with symbol names which aren't constrained in any way. Therefore U[K] isn't known to be constrained to keyof T.

Changing the constraint of U to an object type where all properties are constrained to keyof T does indeed work:

function f2<T, U extends Record<keyof U, keyof T>, K extends keyof U>(obj: T, map: U, key: K) {
    return obj[map[key]];  // Ok
}

@ahejlsberg ahejlsberg added Working as Intended The behavior described is the intended behavior; this is not a bug and removed Domain: Indexed Access Types The issue relates to accessing subtypes via index access Needs Investigation This issue needs a team member to investigate its status. labels Nov 26, 2018
@jack-williams
Copy link
Collaborator

Yep, so it seems like I was completely wrong on this one. The mistake I made was that the PR I linked to only concerned the case when relating to an indexed access type; this example is about relating from an indexed access type. Subtle, but wrong. Sorry!

@weswigham weswigham added the Breaking Change Would introduce errors in existing code label Nov 26, 2018
@weswigham
Copy link
Member

cc @DanielRosenwasser to double-check that we're documenting this break in the 3.2 (? I think that's the first) release.

@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@pikax
Copy link
Author

pikax commented Feb 14, 2019

Sorry to comment on a closed issue, is this suppose to happen:

interface MyGetter {
    vstring : string,
    vnumber: number,

    vhidden: boolean;
}
declare interface TestGeneric<Getters> {
    <Map extends Record<string, keyof Getters>>(map: Map) : { [K in keyof Map]: Getters[Map[K]]}; 
}

declare interface TestSpecific {
    <Map extends Record<string, keyof MyGetter>>(map: Map): { [K in keyof Map]: MyGetter[Map[K]]}
}

declare const genericInterface: TestGeneric<MyGetter>;
declare const speficInterface: TestSpecific;

const generic = genericInterface({
    testString: 'vstring',
    testNumber: 'vnumber'
});
const specific = speficInterface({
    testString: 'vstring',
    testNumber: 'vnumber'
}); 


generic.testNumber; //number
specific.testNumber; // number

generic.testString; // string
specific.testString; //string

TestGeneric is getting a compile error but TestSpecific doesn't, shouldn't the type be correct?

playground

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Breaking Change Would introduce errors in existing code Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants