una tutorial tipos metodos funciones funcion español datos crear como anonima typescript typescript1.8

typescript - tutorial - Obteniendo el tipo de retorno de una función



tipos de datos en angular (8)

El siguiente código funciona sin ejecutar la función. Es de la biblioteca react-redux-typescript ( https://github.com/alexzywiak/react-redux-typescript/blob/master/utils/redux/typeUtils.ts )

interface Func<T> { ([...args]: any, args2?: any): T; } export function returnType<T>(func: Func<T>) { return {} as T; } function mapDispatchToProps(dispatch: RootDispatch, props:OwnProps) { return { onFinished() { dispatch(action(props.id)); } } } const dispatchGeneric = returnType(mapDispatchToProps); type DispatchProps = typeof dispatchGeneric;

Tengo la siguiente función:

function test(): number { return 42; }

Puedo obtener el tipo de la función usando typeof :

type t = typeof test;

Aquí, t será () => number .

¿Hay alguna manera de obtener el tipo de retorno de la función? Me gustaría que t sea number lugar de () => number .


La forma más fácil en TypeScript 2.8:

const foo = (): FooReturnType => { } type returnType = ReturnType<typeof foo>; // returnType = FooReturnType


No hay forma de recuperar el tipo de retorno de la función sin ejecutarla tristemente. Esto se debe a que cuando TypeScript se compila en JS, pierde toda la información sobre el tipo.



Se me ocurrió lo siguiente, que parece funcionar bien:

function returnType<A, B, Z>(fn: (a: A, b: B) => Z): Z function returnType<A, Z>(fn: (a: A) => Z): Z function returnType<Z>(fn: () => Z): Z function returnType(): any { throw "Nooooo" } function complicated(value: number): { kind: ''complicated'', value: number } { return { kind: ''complicated'', value: value } } const dummy = (false as true) && returnType(complicated) type Z = typeof dummy


Si la función en cuestión es un método de una clase definida por el usuario, puede usar decoradores de métodos en conjunción con Reflect Metadata para determinar el tipo de retorno (función del constructor) en tiempo de ejecución (y con él, haga lo que le parezca).

Por ejemplo, puede iniciar sesión en la consola:

function logReturnType( target: Object | Function, key: string, descriptor: PropertyDescriptor ): PropertyDescriptor | void { var returnType = Reflect.getMetadata("design:returntype", target, key); console.log(returnType); }

Simplemente ajuste este decorador de métodos en un método de su elección y tendrá la referencia exacta a la función constructora del objeto que supuestamente se devuelve de la llamada al método.

class TestClass { @logReturnType // logs Number (a string representation) public test(): number { return 42; } }

Sin embargo, existen algunas limitaciones notables para este enfoque:

  • debe definir explícitamente el tipo de retorno en un método decorado como tal; de lo contrario, no se Reflect.getMetadata desde Reflect.getMetadata ,
  • solo puede hacer referencia a tipos reales que también existen después de la compilación; es decir, sin interfaces o genéricos

Además, deberá especificar los siguientes argumentos de la línea de comandos para el compilador de mecanografía, porque tanto los decoradores como los metadatos reflejados son características experimentales al momento de escribir esta publicación:

--emitDecoratorMetadata --experimentalDecorators


EDITAR

A partir de TypeScript 2.8, esto es oficialmente posible con ReturnType<T> .

type T10 = ReturnType<() => string>; // string type T11 = ReturnType<(s: string) => void>; // void type T12 = ReturnType<(<T>() => T)>; // {} type T13 = ReturnType<(<T extends U, U extends number[]>() => T)>; // number[]

Ver here para más detalles.

¡TypeScript es increíble!

Hack de la vieja escuela

La respuesta de Ryan ya no funciona, desafortunadamente. Pero lo modifiqué con un truco del que estoy irracionalmente feliz. Mirad:

const fnReturnType = (false as true) && fn();

Funciona al convertir falso en el valor literal de verdadero, de modo que el sistema de tipos piensa que el valor de retorno es el tipo de la función, pero cuando realmente ejecuta el código, corta los circuitos en falso.

TypeScript es el mejor. :RE


Editar: ¡ Esto ya no es necesario con TS 2.8! ReturnType<F> proporciona el tipo de retorno. Ver respuesta aceptada.

Una variante de algunas de las respuestas anteriores que estoy usando, que funciona en strictNullChecks y oculta un poco la inferencia de gimnasia:

function getReturnType<R>(fn: (...args: any[]) => R): R { return {} as R; }

Uso:

function foo() { return { name: "", bar(s: string) { // doesn''t have to be shorthand, could be `bar: barFn` return 123; } } } const _fooReturnType = getReturnType(foo); export type Foo = typeof _fooReturnType; // type Foo = { name: string; bar(s: string): number; }

Llama a la función getReturnType , pero no llama a la función original. Puede evitar que la llamada getReturnType use (false as true) && getReturnType(foo) pero IMO esto solo lo hace más confuso.

Acabo de usar este método con algunos regexp buscar / reemplazar para migrar un antiguo proyecto Angular 1.x que tenía ~ 1500 funciones de fábrica escritas de esta manera, originalmente en JS, y agregué los tipos de Foo etc. a todos los usos ... increíble el código roto Uno lo encontrará. :)