Skip to content

Object non-literal keys breaks parameter type guard in callback value #29718

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

Open
MasGaNo opened this issue Feb 4, 2019 · 3 comments
Open

Object non-literal keys breaks parameter type guard in callback value #29718

MasGaNo opened this issue Feb 4, 2019 · 3 comments
Labels
Bug A bug in TypeScript
Milestone

Comments

@MasGaNo
Copy link

MasGaNo commented Feb 4, 2019

TypeScript Version: 3.4.0-dev.20190202

Search Terms:
object dynamic keys callback implicit any
duplicate dynamic object key typing
Code

// PLEASE ENABLE => noImplicitAny 

type Keys = 'a' | 'b' | 'c';
type Shape = { [K in Keys]?: K extends string ? (key: K) => K : never };

const getC = () => 'c' as 'c';

export const obj: Shape = {
  ['a']: key => key, // OK => inferred correctly
  ['b' as 'b']: key => key, // Error => inference broken "any" type
  [getC()]: key => key, // Error => inference broken "any" type
  [getC()]: key => key, // Error => inference broken "any" type instead of Duplicate identifier
  ['a']: key => key, // OK => Duplicate identifier as expected
};

Expected behavior:

  • No implicit any error, but correct type assignation
  • Detect duplicate identifier in case of non-explicit literal string key

Actual behavior:

  • When not using an explicit literal string as an object-key, TypeScript cannot infer correctly the value.
  • In a same way, TypeScript cannot detect duplicate identifier

Playground Link:
(http://www.typescriptlang.org/play/#src=%2F%2F%20PLEASE%20ENABLE%20%3D%3E%20noImplicitAny%20%0D%0A%0D%0Atype%20Keys%20%3D%20'a'%20%7C%20'b'%20%7C%20'c'%3B%0D%0Atype%20Shape%20%3D%20%7B%20%5BK%20in%20Keys%5D%3F%3A%20K%20extends%20string%20%3F%20(key%3A%20K)%20%3D%3E%20K%20%3A%20never%20%7D%3B%0D%0A%0D%0Aconst%20getC%20%3D%20()%20%3D%3E%20'c'%20as%20'c'%3B%0D%0A%0D%0Aexport%20const%20obj%3A%20Shape%20%3D%20%7B%0D%0A%20%20%5B'a'%5D%3A%20key%20%3D%3E%20key%2C%20%2F%2F%20OK%20%3D%3E%20inferred%20correctly%0D%0A%20%20%5B'b'%20as%20'b'%5D%3A%20key%20%3D%3E%20key%2C%20%2F%2F%20Error%20%3D%3E%20inference%20broken%20%22any%22%20type%0D%0A%20%20%5BgetC()%5D%3A%20key%20%3D%3E%20key%2C%20%2F%2F%20Error%20%3D%3E%20inference%20broken%20%22any%22%20type%0D%0A%20%20%5BgetC()%5D%3A%20key%20%3D%3E%20key%2C%20%2F%2F%20Error%20%3D%3E%20inference%20broken%20%22any%22%20type%20instead%20of%20Duplicate%20identifier%0D%0A%20%20%5B'a'%5D%3A%20key%20%3D%3E%20key%2C%20%2F%2F%20OK%20%3D%3E%20Duplicate%20identifier%20as%20expected%0D%0A%7D%3B%0D%0A)

Related Issues:

@RyanCavanaugh
Copy link
Member

"b" as "b" should behave the same as "b". Not sure if getC() is practical to recognize as "c" though.

@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.4.0 milestone Feb 4, 2019
@piotrwitek
Copy link

Hey @RyanCavanaugh, what do you mean by not practical for getC() case?
How are we supposed to make the inference working for dynamic key-getter cases?
It's required for creating nice typesafe abstractions as above handlers map without the need to explicitly provide key type for each handler which would be really annoying.

@Zzzen
Copy link
Contributor

Zzzen commented Dec 30, 2020

I think getC() should be recognized as "c", just like key can be inferred in obj[getC()] = key => key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants