2017-05-16 3 views
1

文字列を文字列リテラル結合体に絞りたいと思っています。言い換えれば、文字列がリテラルユニオンの可能な値の1つであるかどうかをチェックしたいので、これは動作します(オペレータcouldbeが存在する場合)。文字列を文字列リテラル結合に絞る

type lit = "A" | "B" | "C"; 
let uni: lit; 
let str = "B"; 
if(str couldbe lit){ 
    uni = str; 
} else { 
    doSomething(str); 
} 

どのようにすればいいですか?

私はif (str instanceof lit)を使ってみましたが、うまくいかないようです。 keyofを使用して文字列共用体を反復処理することは、許可された値がキーそのものではないため、どちらも機能しません。

switchを1つの可能な値ごとに1つ使用することもできますが、許容値が変更されると微妙なエラーが発生する可能性があります。

+1

実行時に 'lit'という型は存在しませんので、そのように使うことはできません。代わりにenumを使用するかもしれませんか? –

+0

switch文のコメントについては、この[answer](https://stackoverflow.com/questions/39419170/how-do-i-check-that-a-switch-block-is-exhaustive-in-typescript)を参照してください。 –

+0

@NitzanTomerこれは実際には非常に良いアイデアですが、はるかにクリーンで理解しやすいようです。 – iFreilicht

答えて

1

User-Defined Type Guardsを使用できます。

type lit = "A" | "B" | "C"; 
let uni: lit; 
let str = "B"; 

function isLit(str: string): str is lit { 
    return str == "A" || str == "B" || str == "C"; 
} 
function doSomething(str: string) { 

} 

if (isLit(str)) { 
    uni = str; 
} 
else { 
    doSomething(str); 
} 

ADD:

重複編集を避けるために、classはコンパイル時の両方に使用することができ、実行時に。これで、1つの場所だけを編集するだけです。

class Lit { 
    constructor(public A = 0, public B = 0, public C = 0) {} 
} 
type lit = keyof Lit; 
let uni: lit; 

function isLit(str: string): str is lit { 
    let lit = new Lit(); 
    return (str in lit) ? true : false; 
} 
+0

Hm、これはswitch文より少し優れていますが、 'lit'が許可された値が変更されたときに型ガードを更新することを忘れる可能性があるという問題があります。 – iFreilicht

+0

私は私の答えに別の解決法を加えました。 – thatseeyou

+0

リテラルの組合を絶対に使用しなければならない場合、私はあなたの第2の解決策を大いに好んでいます。ただ、より良い方法は 'enum'sに切り替えることです。 – iFreilicht

関連する問題