Criando método genérico `toFunc` em Typescript?
Eu tenho um modelo em Ts que preciso preencher com algumas propriedades.
A simplificação do código atual é:
var claimSummaryDetails : {
Name : this._store.selectSync("currentUser")
.Result
.Family
.find(m => m.MemberID == openClaim.Member_ID)
}
Ok. É aqui que as coisas ficam complicadas.
Por favor, note que eu ainda não preenchi name (com uma string) :
Eu tenho um Objeto com muitas opções de "nome" ( englishFirstName/localfirstName)
Ok - então qual nome devo mostrar?
Bem, é por isso que temos um indicador lang chamado isEnglish:boolean
Então, basicamente:
se isEnglish == true, devemos tomar:
{Name: this._store.selectSync("currentUser")
.Result
.Family
.find(m => m.MemberID == openClaim.Member_ID).englishfirstname}
caso contrário
{Name: this._store.selectSync("currentUser")
.Result
.Family
.find(m => m.MemberID == openClaim.Member_ID).localFirstName}
Claro, eu poderia fazer isso:
{Name: isEnglish ? this._store...........englishFirstName : this._store....localFirstName}
Mas por favor, note que ele escaneia a loja duas vezes e é tempo demais.
Ok.
Em C# (há muito tempo) eu criei um método de extensão que me permitia pegar o argumento e fazer o que eu quisesse, não importando o tipo:
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 ));
}
Resultado: 1
Por favor, note isto:
.ToFunc(whatever => isEnglish ?whatever.Prop1 : whatever.Prop2
whatever é o valor de X em X.toFunc e eu tenho acesso às suas propriedades.
isso me economiza de escanear a loja duas vezes e criar variáveis/métodos adicionais
Pergunta
Tentei fazer isso com TS, mas sem sucesso:
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 })
Parque infantil
Como posso corrigir meu código para suportar Generics com .toFunc(a=>a...) para todos os tipos?
Em outras palavras, como posso conseguir isso:
var claimSummaryDetails : {
Name : this._store.selectSync("currentUser")
.Result
.Family
.find(m => m.MemberID == openClaim.Member_ID)
.toFunc(item=>isEnglish ? item.englishFirstName : item.localFirstName)
}
Aliás
Uma solução que me veio à mente é (usando IIFE) :
{Name: ((customer) => this.isEng
? customer.englishfirstname
: customer.localfirstname)(
this._store.selectSync("currentUser")
.Result
.Family
.find(m => m.MemberID == openClaim.Member_ID)) },
Mas eu quero saber se é possível criar um método toFunc tipado em vez disso.
Resposta #1
Embora adicionar um método em Object deva ser cuidadosamente considerado, você pode fazer com que os tipos sejam inferidos se usar um parâmetro genérico para o parâmetro this
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)
Resposta #2
Por que não simplesmente usar um getter em TypeScript, com uma declaração condicional. Um exemplo simples:
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)
