Búsqueda de sitios web

Obtener el tipo de una propiedad de una clase de TypeScript usando el operador keyof


Como se indica en la documentación de TypeScript sobre el operador keyof, se puede obtener una propiedad de una instancia de objeto usando la función a continuación.

function getProperty<T, K extends keyof T>(o: T, name: K) {
    return o[name];
}

Por supuesto, uno puede obtener el tipo de la propiedad reemplazando return o[name] con return typeof o[name]. ¿Hay alguna manera de obtener el tipo de la propiedad sin pasar ninguna instancia de objeto?

function getPropertyType<T>(name: keyof T) {
    // something like T[name]?
}

Respuesta #1

Sí, los tipos de búsqueda funcionan perfectamente:

type BarType = FooType['bar'];

En este caso se espera que FooType sea un objeto como:

type FooType = {
    bar: string;
}

Establece BarType al mismo tipo que FooType['bar'], es decir, a un string.

PD: FooType también puede ser una interfaz o clase.

Respuesta #2

¿Es esto lo que estás buscando?

type PropType<TObj, TProp extends keyof TObj> = TObj[TProp];

y obtener el tipo de una propiedad de un objeto haciendo:

type MyPropType = PropType<ObjType, '<key>'>;

que es lo mismo que la forma de usar Pick en TypeScript, y puede informar un error de compilación si se pasa alguna key no válida.

Actualizaciones

Como sugirió @astoilkov, una alternativa más simple es PropType['key'].

Respuesta #3

Por supuesto, se puede obtener el tipo de la propiedad reemplazando return o[name] por return typeof o[name].

No realmente... si hicieras eso:

function getTypeofProperty<T, K extends keyof T>(o: T, name: K) {
    return typeof o[name];
}

Obtendrías un valor de retorno del tipo "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function", porque estás usando el operador typeof de JavaScript en tiempo de ejecución, el cual devuelve una cadena como "object", no el tipo en tiempo de compilación que maneja TypeScript.

TypeScript también utiliza la palabra clave typeof como el operador de consulta de tipo en tiempo de compilación. Puedes distinguir la diferencia observando los lugares donde aparece. La consulta de tipo typeof solo aparece en lugares donde estás escribiendo un tipo. Por ejemplo:

const a = { foo: 0 };
const b: Array<typeof a> = [{ foo: 1 }, { foo: 2 }, {foo: 3}]; 
const c: string = typeof a; // "object"

En b, puedes ver que typeof a aparece donde escribirías una expresión de tipo, por lo que es una consulta de tipo de TypeScript, y Array<typeof a> se evalúa como Array<{foo: number}>. Por otro lado, en c, typeof a aparece donde escribirías una expresión de valor, por lo que es el operador typeof de JavaScript, y se evaluará como la cadena "object" en tiempo de ejecución.

Como mencionó @k0pernikus, TypeScript no permite (y no pretende permitir) obtener información de tipos en tiempo de compilación en tiempo de ejecución. Así que no existe un operador typeof que actúe en tiempo de ejecución y devuelva información de tiempo de compilación.

Por supuesto, si quieres obtener información de tipo sobre una propiedad en tiempo de compilación, puedes hacer eso, usando lo que se llama tipos de búsqueda. Examinemos el valor de retorno de esa función getProperty():

function getProperty<T, K extends keyof T>(o: T, name: K) {
    return  o[name];
} // hover over getProperty to see that the return value is of type T[K]

Ese T[K] en una posición de tipo significa "el tipo de la propiedad con una clave de tipo K en un objeto de tipo T". Dado que esta es una operación a nivel de tipo, puedes hacerlo en tiempo de compilación sin declarar ningún valor del tipo T o K. Por ejemplo,

type RegExpFlags = RegExp['flags']; // RegExpFlags is string
const flags: RegExpFlags = 'ig';

Aquí, estás consultando la clave "flags" del tipo de objetos RegExp y obteniendo de vuelta el tipo string, y puedes declarar un valor del tipo RegExp['flags'] sin tener un valor del tipo RegExp en ninguna parte.

Eso es lo más cerca que puedo estar de responder a tu pregunta sin más información sobre lo que necesitas. Espero que eso ayude. ¡Buena suerte!

Artículos relacionados