2016-04-25 3 views
3

У меня есть простой тип строковых литералов и нужно проверить его достоверность из-за того, что FFI вызывает «обычный» Javascript. Есть ли способ гарантировать, что определенная переменная является экземпляром любой из этих литералов строк во время выполнения? Что-то вдоль линийПроверка правильности типа объединения строк в runtime?

type MyStrings = "A" | "B" | "C"; 
MyStrings.isAssignable("A"); // true 
MyStrings.isAssignable("D"); // false 

ответ

9

Начиная с TypScript 2.1, вы можете сделать это наоборот with the keyof operator.

Идея заключается в следующем. Поскольку информация типа строкового литерала недоступна во время выполнения, вы определяете простой объект с ключами как ваши литералы строк, а затем создаете тип ключей этого объекта.

Как следует:

// Values of this dictionary are irrelevant 
const myStrings = { 
    A: "", 
    B: "" 
} 

type MyStrings = keyof typeof myStrings; 

isMyStrings(x: string): x is MyStrings { 
    myStrings.hasOwnProperty(x); 
} 

const a: string = "A"; 
if(isMyStrings(a)){ 
    // ... Use a as if it were typed MyString from assignment within this block: the TypeScript compiler trusts our duck typing! 
} 
1

с использованием type только Type Aliasing и он не будет присутствовать в скомпилированный код на JavaScript, которые из-за того, что вы не можете действительно сделать:

MyStrings.isAssignable("A"); 

Что вы можете сделать с это:

type MyStrings = "A" | "B" | "C"; 

let myString: MyStrings = getString(); 
switch (myString) { 
    case "A": 
     ... 
     break; 

    case "B": 
     ... 
     break; 

    case "C": 
     ... 
     break; 

    default: 
     throw new Error("can only receive A, B or C") 
} 

Как для вас вопрос о isAssignable, вы можете:

function isAssignable(str: MyStrings): boolean { 
    return str === "A" || str === "B" || str === "C"; 
} 
+1

Это работает, но ломается, как только 'MyStrings' продолжается без обновления соответствующего' функции isAssignable'. Я надеялся на что-то менее ручное. –

+2

Не так много можно сделать. Как я писал, часть 'type' является строго машинописным текстом и эта информация теряется в сгенерированном js-файле. Вы можете использовать 'enum' вместо этого' type'. –

+2

Если вы хотите приложить усилия, вы можете написать инструмент для генерации TS-кода, который определяет тип И код TS, который проверяет тип выполнения из какого-либо другого источника данных. Я работал над кодом, в котором REST API был написан на C#, и мы скомпилировали контракты данных C# в TS, как определение типа, так и интроспективный объектный литерал, описывающий тип. Понятно, что все это выходит за рамки TS. – Alan

Смежные вопросы