sindresorhus/camelcase-keys

Type 'Interface' does not satisfy the constraint 'readonly any[] | ObjectOptional'.

Opened this issue · 6 comments

Hey folks, I'm using yours lib to fix some third pattern response and types.

The third lib returned me an interface called Places, for example, import type { Places } from "@duffel/api/Places/Suggestions/SuggestionsType";

And I'm using like this:

export type SearchPlacesData = CamelCaseKeys<Places, true>;

export const searchPlaces = async (query: string) => {
  const data = (
    await duffel.suggestions.list({
      query,
    })
  ).data;

  const formattedData = camelcaseKeys<Places[]>(data, { deep: true });


  return formattedData;
};

but when I try to update from v8.0.2 to v9.0.0 I get this error (it's working on 8.0.2):

Type 'Places' does not satisfy the constraint 'readonly any[] | ObjectOptional'.

Which can be reproduced here:

https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAbzgYQIYgKYBs0GcMDSGAnrnAL5wBmUEIcA5AMbrYv4C0A1ibgwFCDgAOxgYoVVEwxwAClikYyCfnDgxQGAPoAvCMIwAuOLhhQRAczgAfOMICuWLAG5+5QTGJgZAJSWP4AF4UVhxUfCJSAB55RVwAPn4gA

and also, on the return it's not showing the correct fields.

before:

image

after:

image

How I can fix this?

I think the essence of the error lies in the index signature part.

Type 'Places' does not satisfy the constraint 'readonly any[] | ObjectOptional'.
  Type 'Places' is not assignable to type 'Record<string, unknown>'.
    Index signature for type 'string' is missing in type 'Places'.(2344)

And the fact that interface cannot be assigned to an indexing signature is as intended by the TypeScript specification, as discussed in the following issue.

microsoft/TypeScript#15300

I think the error can be resolved by using type instead of interface.

Another solution, at least as far as I have experimented, is to shallow-clone the input data, such that you are closing the type off to further augmentation.

This means that typescript can then reliably infer the index signature.

@yutak23 I'm facing the same issue and unfortunately I have no control over whether to use type or interface, since I'm using camelcase-keys on types from a 3rd-party library. I only have this issue since I've upgraded camelcase-keys, before this was working fine. Do you have any other ideas on how to tackle this?

I don't know if this will work because I haven't actually tried it, but would the following method of converting to a type alias work?

interface ThirdPartyInterface {
  hoge: string | null;
  ...
}

type ThirdPartyType = {
  [P in keyof ThirdPartyInterface]: ThirdPartyInterface[P];
};

@yutak23 ah yes that works! it's a bit tedious but it solves my issue for now :). Thanks!

I'm still using the version v8.0.2 I don't see reasons to update for now.