HypeWolf
HypeWolf

Reputation: 850

How to properly interface Object's functions in typescript?

One of the libraries I'm using throw a lot of TS errors. It uses Object functions.

I had multiple TS errors:

error TS2339: Property 'random' does not exist on type 'Object'.
error TS2339: Property 'isArray' does not exist on type 'Object'.
error TS2339: Property 'defineProperties' does not exist on type 'Object'.
error TS2339: Property 'defineProperty' does not exist on type 'Object'.

So I created an Object interface and now I need to define all function used and which type is it. I'm playing with functions and object types. The Window element seems to be working, but the Object element does not.

interface Window {
  Array: Object,
  Object: Object,
  WeakMap: Object,
  Symbol: Object,
  Math: Object,
}

interface Object {
  random: Function,
  isArray: Function,
  defineProperties: Function,
  defineProperty: Function,
  create: Function,
  keys: Function,
  for: Function,
  iterator: Function,
  asyncIterator: Function,
}
declare var window: Window
declare var object: Object

Errors now (15 errors):

index.ts(1432,43): error TS2538: Type 'Object' cannot be used as an index type.
index.ts(1725,23): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Object' has no compatible call signatures.

Trying to use any type results in similar errors but with a lower count (7 errors):

interface Object {
  [index: string]: any
}


error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'Object' has no compatible call signatures.

One of the line:

if (!isValidElement(element) && ObjectHasOwnProperty.call(Object(element), 'default'))

I'm sure there is a better way of doing this. It's a third-party library included in a JS file. I removed some TS errors with // @ts-ignore But I would need to add it on every line, which would be a pain and ts-ignore-start is not yet implemented (https://github.com/Microsoft/TypeScript/issues/19573)

Upvotes: 0

Views: 307

Answers (1)

Bojan Komazec
Bojan Komazec

Reputation: 9526

Object is one of fundamental objects in JavaScript (and so TypeScript) and you should not be trying to redefine it: naming your custom interface as Object is not a good idea.

Just the fact that you want @ts-ignore on the entire code base should have raised you an alert.

I don't know how you are including 3rd party JS in your TS project but from the code snippet you posted I can see that in your TypeScript code you took an object (from library) which has properties random, isArray etc...and declared it to have Object type. When you try to call methods on it, TS compiler complains as JS embedded Object does not have such members. You should rename your custom interface you created (the one which contains random, isArray etc...) so it does not have name Object and use it as a type of that object whose properties you are trying to use. Also, you should apply proper types (TS compiler will complain about using Function) to all members of that interface.

Alternatively (and I think this is probably the way to go when importing JS code), try declaring your imported objects as any and TypeScript compiler won't complain when you use its arbitrary properties.

Upvotes: 1

Related Questions