2015-07-24 3 views
3

Я удивлен, что мы не видели многого о литье в TypeScript Docs. Попытка создать простую функцию tryCast в TypeScript, аналогичную той, которая у нас есть в .Net. Итак, в основном, попробуйте применить к указанному типу, и если fail возвращает null/nothing. Может быть, он должен использовать типографский генератор < 'T>, и как заставить его работать с объектами в дополнение к примитивным типам?Как создать TryCast в TypeScript (.Net Equivalent)

function tryCast(obj: any, type: string) : any { 
    if (typeof obj === type) { 
     switch (type) { 
      case 'number': 
       return Number(obj); 
      case 'string': 
       return String(obj); 
      case 'boolean': 
       return Boolean(obj); 
     } 
    } 

    return null; 
} 

function testCast() { 
    var num: number = 123; 
    var str: string = tryCast(num, 'string'); 

    if (!str) { 
     console.log('Cast failed'); 
    } 
    else { 
     console.log('Cast succeeded'); 
    } 
} 
+0

Как это может быть как машинопись 1.4, так и машинопись 1.5? Выберите * один * тег. – royhowie

+0

@royhowie Хорошо все сделано. – wayofthefuture

ответ

3

Это интересный вопрос. Я не могу придумать хороший сценарий, когда это происходит достаточно часто, чтобы гарантировать общую функцию. В большинстве случаев я бы рассматривал его в каждом конкретном случае. Обычно используют typeof для примитивов и duck typing для пользовательских типов. Однако это хорошее упражнение, поэтому я дам ему выстрел.

Ваш код выполняет проверку typeof, но затем он избыточно передает переменную в конструктор. Если typeof obj === 'number', то у вас уже есть номер, не нужно «бросать». Ниже приведена измененная версия ответа, приведенная @mallison выше. Я также добавил классы для этого решения, однако интерфейсы не работают, как вы могли бы надеяться.

// Overloaded function 
function tryCast(o: number, t: "number"): number; 
function tryCast(o: string, t: "string"): string; 
function tryCast(o: boolean, t: "boolean"): boolean; 
function tryCast(o: IFace, t: "IFace"): IFace; 
function tryCast(o: Function, t: "function"): Function; 
function tryCast<T>(o: any, t: string): T; 
function tryCast<T>(o: T, t: any): T { 
    if (t === typeof o || (o['constructor'] && t === o['constructor']['name'])) { 
     return o; 
    } else { 
     return null; 
    } 
} 

// Usage examples 
var s1 = tryCast(70, 'string'); 
var s2 = tryCast('hello world', 'string'); 
var b1 = tryCast({b:true}, 'boolean'); 
var b2 = tryCast(true, 'boolean'); 
var n1 = tryCast('nan', 'number'); 
var n2 = tryCast(91, 'number'); 

var f1 = tryCast(123, 'function'); 
var f2 = tryCast(function foo() { return 1}, 'function'); 

class Classy { public sanDeigo = true; } 
var c1 = tryCast<Classy>({soFly:false}, 'Classy'); 
var c2 = tryCast<Classy>(new Classy(), 'Classy'); 

interface IFace { eyes: number; hasMouth: boolean; } 
var i1 = tryCast<IFace>({ eyes: 2, fake: true }, 'IFace'); 
var i2 = tryCast<IFace>({ eyes: 2, hasMouth: true }, 'IFace'); 

// Runtime tests 
document.write(` 
    s1:${s1}, // expect null<br/> 
    s2:${s2}, // expect string<br/> 
    b1:${b1}, // expect null<br/> 
    b2:${b2}, // expect boolean<br/> 
    n1:${n1}, // expect null<br/> 
    n2:${n2}, // expect number<br/> 
    f1:${f1}, // expect null<br/> 
    f2:${f2}, // expect function<br/> 
    c1:${c1}, // expect null<br/> 
    c2:${c2}, // expect Classy<br/> 
    i1:${i1}, // expect null<br/> 
    i2:${i2}, // expect IFace...but its not!<br/> 
`); 

// Compiler tests 
s1.toUpperCase(); 
s2.toUpperCase(); 

b1.valueOf(); 
b2.valueOf(); 

n1.toFixed(2); 
n2.toFixed(2); 

f1.apply(this); 
f2.apply(this); 

c1.sanDeigo; 
c2.sanDeigo; 

i1.eyes; 
i2.eyes; 

Если скомпилировать и запустить the code вы увидите следующий вывод:

s1:null, // expect null 
s2:hello world, // expect string 
b1:null, // expect null 
b2:true, // expect boolean 
n1:null, // expect null 
n2:91, // expect number 
f1:null, // expect null 
f2:function foo() { return 1; }, // expect function 
c1:null, // expect null 
c2:[object Object], // expect Classy 
i1:null, // expect null 
i2:null, // expect IFace...but its not! 

Так что же происходит? Не существует общего способа создания интерфейса, поскольку он является объектом компиляции. Время выполнения не знает о интерфейсах. Класс работает, потому что мы знаем, как TypeScript будет компилировать код, но это может не работать в будущем, если имя конструктора не совпадает с именем класса (вы можете проверить спецификацию ES6 перед использованием этого в процессе производства).

Опять же, единственный способ проверить тип интерфейса во время выполнения - это утка, как я упоминал ранее. Я оставлю вас с тем, что я считаю правильным решением для сценария, когда вы не знаете тип во время компиляции.

$.getJSON('data.json', function(data: IFace) { 
    if (data && data.eyes > 0 && data.hasMouth) { 
     // this looks like an IFace to me! 
    } else { 
     // data is no good! 
    } 
}); 
1

Это вы что искали?

interface IFoo { bar: any; } 

function tryCast(obj: number, type: "number"): number; 
function tryCast(obj: string, type: "string"): string; 
function tryCast(obj: boolean, type: "boolean"): boolean; 
function tryCast(obj: IFoo, type: "IFoo"): IFoo; 
function tryCast(obj: any, type: string): any; 
function tryCast(obj: any, type: string): any { 

    // Do fancy stuff to cast things 
} 

// IFoo 
tryCast({ bar: 'hi' }, 'IFoo'); 

// any (NULL) 
tryCast({}, 'string'); 

// boolean 
tryCast(!!1 , 'boolean'); 

// any (NULL) 
tryCast(123, 'boolean'); 

// number 
tryCast(123, 'number'); 

// string 
tryCast(123 + '', 'string');