microsoft / TypeScript

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

globalThis property access errors are behind noImplicitAny, not noImplicitThis #30139

Closed sandersn closed 5 years ago

sandersn commented 5 years ago

Now that globalThis is available, top-level this also has a more precise type, and issues the normal noImplicitAny element access errors for unknown properties:

if (this['unknown']) { ... } // error, `typeof globalThis` has no index signature
if (this.unknown) { ... } // error, `typeof globalThis` has no index signature
this.onmousemove = function () { /* ok, and this: Window */ }

We have a conflict: traditionally, "x has no index signature" errors are produced when noImplicitAny is on. Also traditionally, "this has type any" errors are produced when noImplicitThis is on.

Technically, top-level this no longer has type any, so it's technically correct to issue the errors from behind noImplicitAny. But people might expect to see them only when noImplicitThis is on instead.

Let's discuss at the next design meeting.

sandersn commented 5 years ago

No complaints so far. I think this is fine where it is.

IgorKurkov commented 4 years ago

Hi! Faced this issue Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature. Any updates?

sandersn commented 4 years ago

Can you explain more about your expectations and usage?

  1. Is your usage the same as the bug's example?
  2. Do you expect no error or a different error?
  3. Do you have noImplicitAny: true but noImplicitThis: false? That's the only configuration that would no longer have an error if this bug were fixed.
KevinGruber commented 3 years ago

@sandersn I have exactly that problem with the config noImplicitAny: true and noImplicitThis: false

It worked fine in lower versions (ts 4.2.*) but since the upgrade to ts4.3 it is behaving like that

do you have any idea?

sandersn commented 3 years ago

@KevinGruber nothing comes to mind except maybe external changes to @types/node. Can you open a new issue with more detail about the error you get?

nulldreams commented 3 years ago

@KevinGruber I managed to remove this message with the property "noImplicitAny": false.

ts 4.3.5

bennycode commented 3 years ago

I am getting this error when bumping @types/node from 15.12.4 to 16.7.10.

I have the following defined in my code:

import {APIClient} from '../../APIClient';

declare global {
  module NodeJS {
    interface Global {
      client: APIClient;
    }
  }
}

global.client = new APIClient(APIClient.URL_DEMO, 'global-demo-api-key');
^----- here I am getting the error: TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.
mstaicu commented 3 years ago

@bennycode I had the same issue with exactly the same use case as yours. Seems that the latest @types/node has the following type definition file content

declare var global: typeof globalThis;

Seems that at some point it had a different content

declare var global: NodeJS.Global & typeof globalThis;

What I ended up doing is this ( porting your changes ):

declare global {
  function client(): APIClient;
}

or

declare module globalThis {
  function client(): APIClient;
}
hazem-alabiad commented 3 years ago

@mstaicu Where to put those definitions? in global.d.ts? In which folder?

mstaicu commented 3 years ago

@hazemalabiad I declared the type definitions in my implementation file

stuff.ts

declare global {
  function client(): APIClient;
}

global.client = () => {
  //return a APIClient
};
bennycode commented 3 years ago

Thanks for helping me @mstaicu. My problem is that client is not a function but an instance of APIClient. That's why the following definitions didn't work:

Test:

declare global {
  function client(): APIClient;
}

global.client = new APIClient(APIClient.URL_DEMO, "global-demo-api-key");

Error:

TS2322: Type 'APIClient' is not assignable to type '() => APIClient'.   Type 'APIClient' provides no match for the signature '(): APIClient'.

Test:

declare global {
  client: APIClient;
}

global.client = new APIClient(APIClient.URL_DEMO, "global-demo-api-key");

Error:

TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.

Test:

declare module globalThis {
  function client(): APIClient;
}

global.client = new APIClient(APIClient.URL_DEMO, "global-demo-api-key");

Error:

TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.

I tried to use a getter and setter definition as these are supported since TS 3.6 but it also didn't help:

Test:

declare global {
  get client(): APIClient;
}

Error:

TS2304: Cannot find name 'client'.

Test:

declare module globalThis {
  get client(): APIClient;
}

Error:

TS2304: Cannot find name 'client'.

You can find my attempts here: https://github.com/bennycode/ig-trading-api/pull/288

mstaicu commented 3 years ago

@bennycode what about the following:


declare global {
  var client: String;
}

global.client = "🙈";

Then access global.client where you need to

ctjlewis commented 2 years ago

Somehow, this only works when defining the following way:

declare module global {
  const MY_VAR: string;
}

The following do not work:

declare global { /* ... */ };

declare globalThis { /* ... */ };

declare module globalThis { /* ... */ };

Only declare module global { ... } works, no idea why.

Flaburgan commented 5 days ago

Hello, sorry to revive this 2.5 years later, but I'm facing this issue with Node. Node itself already define the global object in @types/node/globals.global.d.ts:

declare var global: typeof globalThis;

So even if I added the solution above in my typings.d.ts file, I still have the error. Any idea?