usos tricíclicos triciclicos triciclico son sindrome que principales para nombres los funcion farmacos comerciales antidepresivos pattern-matching typescript algebraic-data-types

pattern matching - tricíclicos - ¿Cómo se emulan los ADT y la coincidencia de patrones en TypeScript?



principales farmacos antidepresivos triciclicos (4)

Fui con el siguiente patrón similar al de Visitor, inspirado en esto y esto (en el ejemplo, una Choice puede ser Foo o Bar ):

interface Choice { match<T>(cases: ChoiceCases<T>): T; } interface ChoiceCases<T> { foo(foo: Foo): T; bar(bar: Bar): T; } class Foo implements Choice { match<T>(cases: ChoiceCases<T>): T { return cases.foo(this); } } class Bar implements Choice { match<T>(cases: ChoiceCases<T>): T { return cases.bar(this); } }

Uso:

function getName(choice: Choice): string { return choice.match({ foo: foo => "Foo", bar: bar => "Bar", }); }

La coincidencia en sí misma es expresiva y segura, pero hay mucho que repetir para los tipos.

Desafortunadamente, a partir de la versión 0.9.5, TypeScript aún no (tiene) tipos de datos algebraicos (tipos de unión) y coincidencia de patrones (para desestructurarlos). Además, ni siquiera es compatible con instanceof en las interfaces. ¿Qué patrón usas para emular estas funciones del lenguaje con la máxima seguridad de tipo y el código mínimo repetitivo?



Aquí hay una alternativa a la muy buena respuesta de @thSoft. En el lado positivo, esta alternativa

  1. tiene interoperabilidad potencial con objetos javascript sin formato en la forma { type : string } & T , donde la forma de T depende del valor del type ,
  2. tiene una repetición sustancialmente menor por elección;

en el lado negativo

  1. no hace cumplir estáticamente que coincida con todos los casos,
  2. no distingue entre diferentes ADT.

Se parece a esto:

// One-time boilerplate, used by all cases. interface Maybe<T> { value : T } interface Matcher<T> { (union : Union) : Maybe<T> } interface Union { type : string } class Case<T> { name : string; constructor(name: string) { this.name = name; } _ = (data: T) => ( <Union>({ type : this.name, data : data }) ) $ = <U>(f:(t:T) => U) => (union : Union) => union.type === this.name ? { value : f((<any>union).data) } : null } function match<T>(union : Union, destructors : Matcher<T> [], t : T = null) { for (const destructor of destructors) { const option = destructor(union); if (option) return option.value; } return t; } function any<T>(f:() => T) : Matcher<T> { return x => ({ value : f() }); } // Usage. Define cases. const A = new Case<number>("A"); const B = new Case<string>("B"); // Construct values. const a = A._(0); const b = B._("foo"); // Destruct values. function f(union : Union) { match(union, [ A.$(x => console.log(`A : ${x}`)) , B.$(y => console.log(`B : ${y}`)) , any (() => console.log(`default case`)) ]) } f(a); f(b); f(<any>{});


Contestar

ni siquiera es compatible con instanceof en las interfaces.

La razón es borrado de tipo. Las interfaces son solo una construcción de tipo compilación y no tienen implicaciones de tiempo de ejecución. Sin embargo, puede usar instanceof en las clases, por ejemplo:

class Foo{} var x = new Foo(); console.log(x instanceof Foo); // true