admin管理员组文章数量:1421759
I'm surprised we haven't seen much about casting in the TypeScript Docs. Trying to create a simple tryCast function in TypeScript, similar to the one we have in .Net. So basically, try to cast to the specified type, and if fail return null / nothing. Maybe it should be using the typescript generic <'T> syntax, and how to get it to work with objects in addition to the primitive types?
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');
}
}
I'm surprised we haven't seen much about casting in the TypeScript Docs. Trying to create a simple tryCast function in TypeScript, similar to the one we have in .Net. So basically, try to cast to the specified type, and if fail return null / nothing. Maybe it should be using the typescript generic <'T> syntax, and how to get it to work with objects in addition to the primitive types?
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');
}
}
Share
Improve this question
edited Jul 25, 2015 at 15:12
wayofthefuture
asked Jul 24, 2015 at 22:36
wayofthefuturewayofthefuture
9,4757 gold badges38 silver badges55 bronze badges
2
- How can this be both typescript 1.4 and typescript 1.5? Pick one tag. – royhowie Commented Jul 25, 2015 at 3:52
- @royhowie Ok all done. – wayofthefuture Commented Jul 25, 2015 at 15:12
2 Answers
Reset to default 2This is an interesting question. I can't think of a good scenario where this is happening often enough to warrant a generic function. Most of the time, I would handle it on a case-by-case basis. Typically use typeof
for primitives and duck typing for user-defined types. However this is a good exercise so I'll give it shot.
Your code is performing the typeof
check but then it redundantly passes the variable to a constructor. If typeof obj === 'number'
then you already have a number, no need to "cast". Here is a modified version of the answer given by @mallison above. I also added a Classes to this solution however Interfaces do not work as you might hope.
// 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;
If you pile and run the code you'll see the following output:
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!
So what's going on? There's no general way to cast an interface because it is a pile-time entity. The runtime doesn't know about interfaces. The class works because we know how TypeScript will pile the code but this might not work in the future if the constructor name is not the same as the class name (you might want to check the ES6 spec before using this in production).
Again, the only way to check an interface type at runtime is duck typing as I mentioned earlier. I will leave you with what I think the proper solution to a scenario where you wouldn't know the type at pile time.
$.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!
}
});
Is this what you're looking for?
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');
本文标签: javascriptHow to create TryCast in TypeScript ( Net Equivalent )Stack Overflow
版权声明:本文标题:javascript - How to create TryCast in TypeScript ( .Net Equivalent ) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745333590a2653933.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论