

typescriptで書いています。あるアプリケーションでサポートする言語（locale）が限定されていて、システムがそれ以外のlocaleを返したらデフォルトのlocaleにフォールバックするための関数を書きたいです。

`/* currentLocaleがSupportedLocaleだったら */`はどう書けばいいのでしょうか？

[code]

    type SupportedLocale = 'ja' | 'en';
    
    export function currentLocale() : SupportedLocale{
      // システムからlocaleを取る。
      const currentLocale =  Localization.locale.split('-')[0];
    
      if(/* currentLocaleがSupportedLocaleだったら */){
        return currentLocale
      }
    
      return 'ja';  
    }
    
[/code]

型ガードあたりで検索すると、以下の様な記述というのは出てきますが、これだとサポートするlocaleが増えた時、二箇所に変更を加えるのが嫌です。

[code]

    export function currentLocale() : SupportedLocale{
      const currentLocale =  Localization.locale.split('-')[0];
    
      if(currentLocale == 'ja' || currentLocale == 'en'){
        return currentLocale;
      }
    
      return 'ja';  
    }
    
[/code]

typeofはと思ったけど、これはそもそも`typeof currentLocale`が`string`だろうし、`'SupportedLocale'
only refers to a type, but is being used as a value
here.ts(2693)`と言われ左辺には置けないようですね。

[code]

      if(typeof currentLocale === SupportedLocale){
        return currentLocale;
      }
    
[/code]

ユーザー定義型ガードというのを見つけて使ってみたけど、結局のところ二箇所にサポートlocaleの情報が散らばってしまいます。

[code]

    export type SupportedLocale = 'ja' | 'en';
    
    const isSupportedLocale = (test: unknown): test is SupportedLocale => {
      if(test == 'ja' || test == 'en'){
        return true;
      }
    
      return false;
    };
    
    export function currentLocale() : SupportedLocale{
      const currentLocale =  Localization.locale.split('-')[0];
    
      if(isSupportedLocale(currentLocale)){
        return currentLocale;
      }
    
      return 'ja';  
    }
    
[/code]

まあ、やってることはIF文でやった型ガードを関数に切り出しただけですよね。サポートするlocaleのリストを一箇所だけに書いて、判定するにはどう書けばいいのでしょうか？


CC BY-SA 4.0
2022-03-09T04:41:19.297
86768
2022-03-10T03:47:02.260
2022-03-10T03:47:02.260
3060
15048
question
javascript typescript
typescriptで指定した文字列のどれかを返す関数を定義したい


許容される値の配列から Union 型を生成することで、今回の問題を簡潔に解決できます。この手法は一般的に利用できるでしょう。

[code]

    // refer https://stackoverflow.com/a/45257357
    const _SupportedLocale = [
      'ja',
      'en'
    ] as const
    type SupportedLocale = typeof _SupportedLocale[number]
    
    // refer https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
    const _SupportedLocaleValues: readonly string[] = _SupportedLocale
    
    function isSupportedLocale(str: string): str is SupportedLocale {
      return _SupportedLocaleValues.includes(str)
    }
    
    /* apply it to your code...
    const DEFAULT_LOCALE: SupportedLocale = 'ja'
    
    export function currentLocale(): SupportedLocale {
      const currentLocale = Localization.locale.split('-')[0]
      if (isSupportedLocale(currentLocale)) {
        return currentLocale
      }
      return DEFAULT_LOCALE
    }
    */
    
    // for example...
    console.log('ja', isSupportedLocale('ja'))
    // true
    console.log('en', isSupportedLocale('en'))
    // true
    console.log('zh', isSupportedLocale('zh'))
    // false
    
[/code]


CC BY-SA 4.0
2022-03-09T05:31:42.963
86770
2022-03-09T05:31:42.963
86768
answer