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

时间:2018-06-27 17:20:42

标签: javascript typescript

我已经编写了一种模仿Null条件运算符/ Elvis运算符的方法,包括自动完成数组支持:

说我有这个对象:

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

我可以访问数组中的第二个元素并获取a

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

我所做的是使表达式作为函数发送,然后可以将其解析为字符串:

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符合预期,但我有一个小问题。

方法的签名返回any

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

问题:

是否可以选择将返回值更具体(甚至更精确)作为我尝试访问的道具?

所以n(o, (k) => k.a.b.c[1].a)将是:number 并且n(o, (k) => k.a.b.s)将是:string

有可能吗?如果不是,是否有办法使返回值更“典型”?


Link for comment

1 个答案:

答案 0 :(得分:3)

您可以为返回值添加一个额外的类型参数,然后让编译器确定类型参数是表达式的返回类型:

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

注意 |null部分是可选的,但在实现环境中有意义。