【问题标题】:Return dynamic compile time type in Typescript?在 Typescript 中返回动态编译时间类型?
【发布时间】:2018-06-28 01:51:58
【问题描述】:

我已经写了一个方法来模仿Null条件运算符/猫王运算符,包括自动完成数组支持:

假设我有这个对象:

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) =&gt; k.a.b.c[1].a) 将是:numbern(o, (k) =&gt; k.a.b.s) 将是:string

有可能吗?如果没有,有没有办法让返回值更“典型”?


Link for comment

【问题讨论】:

    标签: javascript typescript


    【解决方案1】:

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

    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 部分是可选的,但在您的实现上下文中是有意义的。

    【讨论】:

    • 谢谢!但是,我do have one any left at the end...问题是o 总是有一个新类型(在每次迭代中)。可以修吗?
    • 你的意思是完全未知?如果是这样,即使是表达式也没有真正检查过。如果你提供一个完整的例子,我可以看看:-)
    • 我在底部的主要问题处添加了一个链接(因为 url 太长,无法放入 cmets)。
    • @RoyiNamir 哦,对不起,我误会了,我以为你在通话现场不知道T。实现中的any是不可避免的。我添加了不使用断言的方法体,但any 是必要的。不过,呼叫站点将是安全的:)
    • 嗨 - 你能看看here吗?
    猜你喜欢
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 2017-03-05
    • 2018-07-27
    • 1970-01-01
    • 2016-05-06
    相关资源
    最近更新 更多