I've written a method to imitate the Null conditional operator / Elvis operator , including autocomplete and array support :
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
:
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
:
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
Is it possible ? if not , is there a way to make return value to be more "typi" ?
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:
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.