简体   繁体   中英

Creating `toFunc` generic method in Typescript?

I have a model in Ts which I need to populate with some properties.

Current code simplification is :

var  claimSummaryDetails :   {
                  Name :  this._store.selectSync("currentUser") 
                                   .Result
                                   .Family
                                   .find(m => m.MemberID == openClaim.Member_ID)
                }

Ok. This is where things get complicated.
Please notice that I don't have name populated yet (with a string) :

在此处输入图片说明

I have an Object with many "name" options ( englishFirstName / localfirstName )

Ok - so which name should I show ?

Well that's why we have a lang indicator called isEnglish:boolean

So basically :

if isEnglish ==true , we should take :

{Name: this._store.selectSync("currentUser")
.Result
.Family
.find(m => m.MemberID == openClaim.Member_ID).englishfirstname}

otherwise

{Name: this._store.selectSync("currentUser")
.Result
.Family
.find(m => m.MemberID == openClaim.Member_ID).localFirstName}

Sure , I could do this :

{Name: isEnglish  ? this._store...........englishFirstName : this._store....localFirstName}

But please notice that it scans the store twice and it's way too long.

Ok.

In C# (long time ago) I've created an extension method which allowed me to take the argument and do whatever I want , no matter what type :

public static class A
{
    public static Tout ToFunc<T, Tout>(this T obj, Func<T, Tout> f)
    {
        return f(obj);
    }
}

class Person
{
    public int Prop1 { get; set; }
    public int Prop2 { get; set; }
}

void Main()
{
    bool isEnglish = true;
    Person[] a = new Person[] { new Person() { Prop1 = 1,Prop2=100 }, new Person() { Prop1 = 2,Prop2=200 }, new Person() { Prop1 = 3,Prop2=300 } };

    Console.WriteLine(a.First().ToFunc(whatever => isEnglish ?whatever.Prop1 : whatever.Prop2 ));

}

Result : 1

Please notice this :

.ToFunc(whatever => isEnglish ?whatever.Prop1 : whatever.Prop2 

whatever is the value of X in X.toFunc and I have access to its props .

this saves me to scan twice the store , and creat additional variables/methods

Question

I've tried to do this with TS , but without success :

interface Object {
    toFunc(a:(a)=>any): any;
}
Object.prototype.toFunc = function  (f:(a)=>any){
    f();
}


var g= [{a:1,b:2}]
let res= g.find(d => d.a == 1).toFunc((a) => { if (a.a == 1) return 1; else return 2 })

Playground

How can I fix my code to support Generics with .toFunc(a=>a...) for every type ?

In other words , how can I achieve this :

var  claimSummaryDetails :   {
                  Name :  this._store.selectSync("currentUser") 
                                   .Result
                                   .Family
                                   .find(m => m.MemberID == openClaim.Member_ID)
                                   .toFunc(item=>isEnglish ? item.englishFirstName : item.localFirstName)
            }

BTW

One solution that have crossed my mind is ( using IIFE) :

    {Name: ((customer) => this.isEng 
                             ? customer.englishfirstname 
                             : customer.localfirstname)(
this._store.selectSync("currentUser")                                                                          
.Result
.Family
.find(m => m.MemberID == openClaim.Member_ID))  },

But I want to know if it's possible to create a typed toFunc method instead.

While adding a method on Object should be carefully considered, you can get the types to be inferred if you use a generic parameter for the this parameter

interface Object {
    toFunc<T, R>(this: T, fn:(a: T)=> R): R;
}
Object.prototype.toFunc = function <T, R> (this:T, f:(a:T)=> R){

    return f(this);

}


var g= [{a:1,b:2}]
var result = g.find(d => d.a == 1).toFunc(i => this.isEng ? i.a : i.b)

Why not simply use getter in typescript, with a conditional statement. A simple example:

class Family {

    isEnglish = false;
    firstName = "FirstName"
    lastName = "LastName"

    constructor(isEnglish: boolean) {
        this.isEnglish = isEnglish;
     }

    get getName(): string{

        if (this.isEnglish) {
            return this.firstName
        } else {
            return this.lastName
        }

    }


}



let family = new Family(true);
alert(family.getName)

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.

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