Skip to content

Suggestion: Add signature for Object.keys() to remove "element implicitly has an 'any'" error #13989

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

Closed
nitzantomer opened this issue Feb 10, 2017 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@nitzantomer
Copy link

nitzantomer commented Feb 10, 2017

When using noImplicitAny the following code:

interface Point3D {
    x: number;
    y: number;
    z: number;
}

let p1: Point3D = { x: 0, y: 0, z: 0 };
let p2 = {} as Point3D;
Object.keys(p1).forEach(key => p2[key] = p1[key]);

Results with the following error:

error TS7017: Element implicitly has an 'any' type because type 'Point3D' has no index signature

There are ways to avoid it:

  1. Use suppressImplicitAnyIndexErrors
  2. Adding an index signature to the interface
  3. Cast p2 and p1 to any
  4. Don't use noImplicitAny

There's another option:

type keys = keyof Point3D;
(Object.keys(p1) as keys[]).forEach(key => p2[key] = p1[key]);

That can be supported by adding a signature for Object.keys in the lib.d.ts:

interface ObjectConstructor {
    ...
    keys(o: any): string[];
    keys<T>(o: T): (keyof T)[];
}

Then the original code would work without the need for suppressImplicitAnyIndexErrors.

@mhegazy
Copy link
Contributor

mhegazy commented Feb 14, 2017

Just to be clear, the error is correct to me. Types in typescript are not final, so there is no guarantees that p1 does not have more keys.. consider:

function fix(p: Point3D) {
    Object.keys(p).forEach(key => p[key] = p[key].toFixed()); // p[comment] does not have 
}

let p1 = { x: 0, y: 0, z: 0, comment: "my 3d point" };
fix(p1);

If you are sure, then cast before access. Alternatively, you can define an index signature on your Point3D.

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Feb 14, 2017
@KostyaTretyak
Copy link

KostyaTretyak commented Mar 3, 2017

Alternatively, you can define an index signature on your Point3D

@mhegazy, but if we define this way, its not works:

type WithSignaturePoint3D = { [P in 'x' | 'y' | 'z']: number };

function fix(p: WithSignaturePoint3D)
{
  // Why here throw error?
  Object.keys(p).forEach(key => console.log(p[key]) );
}

@mhegazy
Copy link
Contributor

mhegazy commented Mar 3, 2017

{ [P in 'x' | 'y' | 'z']: number } === { x: number; y: number; z: number }. So not sure i understand the question.

@KostyaTretyak
Copy link

@mhegazy, you say that

Alternatively, you can define an index signature on your Point3D

I define WithSignaturePoint3D with index signature, but TypeScript still throw error.

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