Por ejemplo, tengo estos tipos:
class User extends Entity {} class Post extends Entity {} type Entities = { user: User, post: Post, // potentially hundreds more }; type EntityType = 'user' | 'post' | ...; Cuando uso Entities y EntityType en genéricos, se ralentiza notablemente Typescript. Se tarda varios minutos en mostrar la información de tipo en VS Code. Tengo funciones genéricas como:
function getEntityFromCache<T extends EntityType>(type: T, id: number): Entities[T] | null | undefined; function getEntity<T extends EntityType>(type: T, id: number): Entities[T] | null { const cachedEntity = getEntityFromCache(type, id); if (cachedEntity !== undefined) { return cachedEntity; } ... } Entiendo por qué esto es lento porque Entities[T] es una unión de todos los valores de Entities , es decir, User | Post | ... . TS no maneja bien los sindicatos. Para verificar que el tipo de devolución de cached sea correcto, TS debe iterar a través de todos los valores posibles de T . Es decir, si T = 'user' , verifique que cachedEntity sea Entities['user'] ; si T = 'post' , verifique que cachedEntity sea Entities['post'] ; y así. Es lento porque TS tiene que verificar cada valor de la unión cada vez que tengo un genérico.
Además, en lugar de solo comparar valores genéricos ( 'user' === 'user' , 'post' === 'post' ), TS compara la entidad completa ( User === User , Post === Post ). Esto lo empeora porque las entidades son complicadas.
¿Cuáles son algunas maneras de acelerar esto? Aquí hay algunas ideas que tengo:
Elimine los genéricos de las funciones intermedias y haga que devuelvan el tipo de entidad base, luego escriba la conversión. Por ejemplo function getEntityFromCache(type: T, id: number): Entity | null | undefined;
De alguna manera, haga que TS compare la cadena de tipo de entidad en lugar de comparar las entidades completas.
De acuerdo con la página wiki de TypeScript Preferir tipos base sobre uniones Vale la pena usar subtipos, en lugar de uniones.
Sin embargo, también tienen un costo. Cada vez que se pasa un argumento a printSchedule, debe compararse con cada elemento de la unión. Para una unión de dos elementos, esto es trivial y económico. Sin embargo, si su unión tiene más de una docena de elementos, puede causar problemas reales en la velocidad de compilación. Por ejemplo, para eliminar miembros redundantes de una unión, los elementos deben compararse por pares, lo cual es cuadrático. Este tipo de verificación puede ocurrir cuando se cruzan uniones grandes, donde la intersección sobre cada miembro de la unión puede dar como resultado tipos enormes que luego deben reducirse. Una forma de evitar esto es usar subtipos, en lugar de uniones.
Ejemplo reducido de los documentos:
interface A { char: 'a' | 'b' | 'c' | 'd' | 'e'; } interface B extends A { char: 'a' | 'b'; } interface C extends A { char: 'd' | 'e'; } declare function char(schedule: A): void;