简体   繁体   English

在Typescript中返回动态编译时间类型?

[英]Return dynamic compile time type in Typescript?

I've written a method to imitate the Null conditional operator / Elvis operator , including autocomplete and array support : 我编写了一个模拟Null条件运算符/ Elvis运算符的方法,包括自动完成数组支持:

Say I have this object : 说我有这个对象:

var o = { a: { b: { c:[{a:1},{a:2}] , s:"hi"} } };

I can access the second element in the array and fetch a : 我可以在阵列中访问所述第二元件和取a

if ( n(o, (k) => k.a.b.c[1].a) == 2 ) 
 {
    alert('Good'); //true
 }

What I've done was to cause the expression to be sent as a function , which then I can parse as string : 我所做的是使表达式作为一个函数发送,然后我可以解析为字符串:

function n<T>(o :T , action : (a:T)=>any):any { 
    let s = action.toString().toString().split('return')[1].split('}')[0].split(';')[0];
    s = s.replace(/\[(\w+)\]/g, '.$1'); //for  array access
    s = s.replace(/^\./, '');    //remove first dot        
    var a = s.split('.');
    for (var i = 1, n = a.length; i < n; ++i) {   //i==0 is the k itself  ,aand we dont need it
        var k = a[i];
        if ( o && o.hasOwnProperty(k)) {
            o = o[k];
        } else {
            return null;
        }
    }
    return o;
}

It does work as expected , but I have a small problem. 它确实按预期工作 ,但我有一个小问题。

The signature of the method returns any : 该方法的签名返回any

function n<T>(o :T , action : (a:T)=>any) :any 
                                           ^^^ 

Question: 题:

Is there any option that the return value will more specific ( or even exact) as the prop I'm trying to access ? 是否有任何选项可以使返回值更具体(甚至精确)作为我试图访问的道具?

So n(o, (k) => kabc[1].a) will be :number and n(o, (k) => kabs) will be :string 所以n(o, (k) => kabc[1].a)将是:numbern(o, (k) => kabs)将是:string

Is it possible ? 可能吗 ? if not , is there a way to make return value to be more "typi" ? 如果没有,有没有办法让返回值更“典型”?


Link for comment 链接评论

You can just add an extra type parameter for the return value and let the compiler figure out that the type parameter is the return type of the expression: 您只需为返回值添加一个额外的类型参数,并让编译器确定type参数是表达式的返回类型:

var o = { a: { b: { c: [{ a: 1 }, { a: 2 }], s: "hi" } } };
function n<T, TValue>(o: T, action: (a: T) => TValue): TValue | null {
    let s = action.toString().toString().split('return')[1].split('}')[0].split(';')[0];
    s = s.replace(/\[(\w+)\]/g, '.$1'); //for  array access
    s = s.replace(/^\./, '');    //remove first dot        
    var a = s.split('.');
    let result: any = o
    for (var i = 1, n = a.length; i < n; ++i) {   //i==0 is the k itself  ,aand we dont need it
        var k = a[i];
        if ( result && result.hasOwnProperty(k)) {
            result = result[k];
        } else {
            return null;
        }
    }
    return result;
}


let nr = n(o, (k) => k.a.b.c[1].a) // is number | null

var str = n(o, (k) => k.a.b.s) // is string | null

Note The |null part is optional but makes sense in the context of your implementation. 注意 |null部分是可选的,但在实现的上下文中是有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM