Jim
Jim

Reputation: 385

Type error when using Array.find with a custom type

I have an object containing a list of supported languages. I'd like to find the user's browser contains one of the languages:

const userLanguage = browserLanguages.find(language => !!supported[language]);

However, I'm getting the following error: Element implicitly has an 'any' type because type 'LanguageName' has no index signature.

LanguageName is a type I've created for my supported object:

type LanguageName = {
  [language in SupportedLanguages]: string;
};

And supportedLanguages is a type containing all languages supported by our app:

type SupportedLanguages = 'en' | 'es';

DEMO

Upvotes: 1

Views: 59

Answers (1)

jcalz
jcalz

Reputation: 327819

I think you'll get the best results by explicitly invoking the overload of Array.find() which treats the callback as a user-defined type guard. Note that you have to do this via manual annotation; the compiler does not currently infer type guards from function return values.

There are multiple ways to do this; here's one:

// make an explicit type guard for SupportedLanguages    
function supportedLanguageGuard<T extends keyof any>(
  x: T
): x is T & SupportedLanguages {
  return !!(supported as any)[x];
}

// use it
const userLanguage: SupportedLanguages | undefined = browserLanguages.find(
  supportedLanguageGuard
); // okay

I went this way because it should work whether or not you narrow browserLanguages to keep track of the literals inside it

const browserLanguages = ["fr", "es"] as const; // TS3.4+

Okay, hope that helps. Good luck!

Link to code

Upvotes: 2

Related Questions