example - typescript react
TypeScript 2: tipificaciones personalizadas para módulo npm sin tipo (4)
Después de probar las sugerencias publicadas en otros lugares , no puedo ejecutar un proyecto mecanografiado que utiliza un módulo NPM sin tipo. A continuación se muestra un ejemplo mínimo y los pasos que probé.
Para este ejemplo mínimo, pretendemos que
lodash
no tiene definiciones de tipo existentes.
Como tal, ignoraremos el paquete
@types/lodash
e intentaremos agregar manualmente su archivo de
lodash.d.ts
a nuestro proyecto.
Estructura de carpetas
-
nodo_módulos
- lodash
-
src
- foo.ts
-
tipings
-
personalizado
- lodash.d.ts
- global
- index.d.ts
-
personalizado
- package.json
- tsconfig.json
- typings.json
A continuación, los archivos.
Archivo
foo.ts
///<reference path="../typings/custom/lodash.d.ts" />
import * as lodash from ''lodash'';
console.log(''Weeee'');
El archivo
lodash.d.ts
se copia directamente del paquete original
@types/lodash
.
Archivo
index.d.ts
/// <reference path="custom/lodash.d.ts" />
/// <reference path="globals/lodash/index.d.ts" />
Archivo
package.json
{
"name": "ts",
"version": "1.0.0",
"description": "",
"main": "index.js",
"typings": "./typings/index.d.ts",
"dependencies": {
"lodash": "^4.16.4"
},
"author": "",
"license": "ISC"
}
Archivo
tsconfig.json
{
"compilerOptions": {
"target": "ES6",
"jsx": "react",
"module": "commonjs",
"sourceMap": true,
"noImplicitAny": true,
"experimentalDecorators": true,
"typeRoots" : ["./typings"],
"types": ["lodash"]
},
"include": [
"typings/**/*",
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
Archivo
typings.json
{
"name": "TestName",
"version": false,
"globalDependencies": {
"lodash": "file:typings/custom/lodash.d.ts"
}
}
Como puede ver, he probado muchas formas diferentes de importar tipings:
-
foo.ts
directamente enfoo.ts
-
Por una propiedad de
typings
enpackage.json
-
Al usar
typeRoots
entsconfig.json
con un archivotypings/index.d.ts
-
Mediante el uso de
types
explícitos entsconfig.json
-
Al incluir el directorio de
types
entsconfig.json
-
Al hacer un archivo
typings.json
personalizado y ejecutartypings install
Sin embargo, cuando ejecuto Typecript:
E:/temp/ts>tsc
error TS2688: Cannot find type definition file for ''lodash''.
¿Qué estoy haciendo mal?
Desafortunadamente, estas cosas actualmente no están muy bien documentadas, pero incluso si pudo hacer que funcionara, repasemos su configuración para que comprenda qué está haciendo cada parte y cómo se relaciona con la forma en que los procesos mecanografiados y las tipificaciones de carga.
Primero repasemos el error que está recibiendo:
error TS2688: Cannot find type definition file for ''lodash''.
Este error en realidad no proviene de sus importaciones o referencias o su intento de usar lodash en cualquier parte de sus archivos ts.
Más bien proviene de un malentendido sobre cómo usar las propiedades
typeRoots
y
types
, así que entremos un poco más en detalle sobre ellas.
Lo que pasa con las
typeRoots:[]
y
types:[]
es que
NO
son formas de uso general para cargar archivos de declaración arbitraria (
*.d.ts
).
Estas dos propiedades están directamente relacionadas con la nueva característica TS 2.0 que permite empaquetar y cargar declaraciones de tipado de paquetes NPM .
Es muy importante comprender que funcionan solo con carpetas en formato NPM (es decir, una carpeta que contiene un paquete.json o index.d.ts ).
El valor predeterminado para
typeRoots
es:
{
"typeRoots" : ["node_modules/@types"]
}
De manera predeterminada, esto significa que el mecanografiado irá a la carpeta
node_modules/@types
e intentará cargar cada subcarpeta que encuentre allí como un
paquete npm
.
Es importante comprender que esto fallará si una carpeta no tiene una estructura similar a un paquete npm.
Esto es lo que está sucediendo en su caso, y la fuente de su error inicial.
Ha cambiado typeRoot para ser:
{
"typeRoots" : ["./typings"]
}
Esto significa que el mecanografiado ahora escaneará la carpeta
./typings
busca de
subcarpetas
e intentará cargar cada subcarpeta que encuentre como un módulo npm.
Supongamos que acaba de configurar
typeRoots
para apuntar a
./typings
pero aún no tenía ningún
types:[]
configuración de propiedad.
Es probable que vea estos errores:
error TS2688: Cannot find type definition file for ''custom''.
error TS2688: Cannot find type definition file for ''global''.
Esto se debe a que
tsc
está escaneando su carpeta
./typings
y buscando las subcarpetas
custom
y
global
.
Luego está tratando de interpretarlos como tipeo tipo paquete npm, pero no hay
index.d.ts
o
package.json
en estas carpetas, por lo que obtiene el error.
Ahora hablemos un poco sobre los
types: [''lodash'']
propiedad
types: [''lodash'']
que está configurando.
¿Qué hace esto?
Por defecto, mecanografiado cargará
todas
las subcarpetas que encuentre dentro de sus
typeRoots
.
Si especifica una propiedad
types:
solo cargará esas subcarpetas específicas.
En su caso, le está diciendo que cargue la carpeta
./typings/lodash
pero no existe.
Es por eso que obtienes:
error TS2688: Cannot find type definition file for ''lodash''
Así que resumamos lo que hemos aprendido.
TypeScript 2.0 introdujo
typeRoots
y
types
para cargar archivos de declaración empaquetados en
paquetes npm
.
Si tiene tipificaciones personalizadas o archivos
d.ts
sueltos que no están contenidos dentro de una carpeta siguiendo las convenciones del paquete npm, entonces estas dos nuevas propiedades no son lo que desea usar.
Typecript 2.0 realmente no cambia cómo se consumirían.
Solo tiene que incluir estos archivos en su contexto de compilación de una de las muchas formas estándar:
-
.ts
directamente en un archivo.ts
:///<reference path="../typings/custom/lodash.d.ts" />
-
Incluyendo
./typings/custom/lodash.d.ts
en susfiles: []
propiedadfiles: []
. -
Incluyendo
./typings/index.d.ts
en susfiles: []
propiedadfiles: []
(que luego incluye recursivamente los otros tipos). -
Agregar
./typings/**
a suincludes:
Con suerte, en base a esta discusión, podrá decir por qué los cambios que le
tsconfig.json
a su
tsconfig.json
hicieron que las cosas volvieran a funcionar.
EDITAR:
Una cosa que olvidé mencionar es que las propiedades
typeRoots
y
types
realmente solo son útiles para la carga
automática
de declaraciones globales.
Por ejemplo si tu
npm install @types/jquery
Y está utilizando el tsconfig predeterminado, entonces ese paquete de tipos jquery se cargará automáticamente y
$
estará disponible en todos sus scripts sin tener que hacer más
///<reference/>
o
import
La
typeRoots:[]
está destinada a agregar ubicaciones adicionales desde donde los
paquetes de
tipo se cargarán automáticamente.
Los
types:[]
el caso de uso principal de la propiedad
types:[]
es deshabilitar el comportamiento de carga automática (configurándolo en una matriz vacía) y luego solo enumerar los tipos específicos que desea incluir globalmente.
La otra forma de cargar paquetes de tipos desde los distintos
typeRoots
es usar la nueva directiva
///<reference types="jquery" />
.
Observe los
types
lugar de la
path
.
Nuevamente, esto solo es útil para los archivos de declaración global, generalmente aquellos que no
import/export
.
Ahora, aquí está una de las cosas que causa confusión con
typeRoots
.
Recuerde, dije que
typeRoots
se trata de la inclusión global de módulos.
Pero
@types/folder
también está involucrado en la resolución estándar del módulo (independientemente de la configuración de
typeRoots
).
Específicamente, la importación explícita de módulos siempre omite todas las opciones de
includes
,
excludes
,
files
,
typeRoots
y
typeRoots
.
Entonces cuando lo haces:
import {MyType} from ''my-module'';
Todas las propiedades mencionadas anteriormente se ignoran por completo.
Las propiedades relevantes durante la
resolución del módulo
son
baseUrl
,
paths
y
moduleResolution
.
Básicamente, cuando se utiliza la resolución del módulo de
node
, comenzará a buscar un nombre de archivo
my-module.ts
,
my-module.tsx
,
my-module.d.ts
comenzando en la carpeta señalada por su configuración
baseUrl
.
Si no encuentra el archivo, buscará una carpeta llamada
my-module
y luego buscará un
package.json
con una propiedad de
typings
, si hay
package.json
o no hay
typings
propiedad de
typings
dentro que le
typings
qué archivo cargar luego buscará
index.ts/tsx/d.ts
dentro de esa carpeta.
Si todavía no tiene éxito, buscará estas mismas cosas en la carpeta
node_modules
comenzando en su
baseUrl/node_modules
.
Además, si no encuentra estos, buscará los
baseUrl/node_modules/@types
para todas las mismas cosas.
Si todavía no encuentra nada, comenzará a ir al directorio principal y buscará
node_modules
y
node_modules/@types
allí.
Seguirá subiendo los directorios hasta que llegue a la raíz de su sistema de archivos (incluso obteniendo módulos de nodo fuera de su proyecto).
Una cosa que quiero enfatizar es que la resolución del módulo ignora completamente cualquier tipo de
typeRoots
que establezca.
Entonces, si configuró
typeRoots: ["./my-types"]
, esto no se buscará durante la resolución explícita del módulo.
Solo sirve como una carpeta donde puede colocar archivos de definición global que desee poner a disposición de toda la aplicación sin necesidad de importar o hacer referencia.
Por último, puede anular el comportamiento del módulo con asignaciones de ruta (es decir, la propiedad de
paths
).
Entonces, por ejemplo, mencioné que no se consulta ningún
typeRoots
personalizado al intentar resolver un módulo.
Pero si te gustó puedes hacer que este comportamiento suceda así:
"paths" :{
"*": ["my-custom-types/*", "*"]
}
Lo que esto hace es para todas las importaciones que coinciden con el lado izquierdo, intente modificar la importación como en el lado derecho antes de intentar incluirla (el
*
en el lado derecho representa su cadena de importación inicial. Por ejemplo, si importa:
import {MyType} from ''my-types'';
Primero intentaría importar como si hubiera escrito:
import {MyType} from ''my-custom-types/my-types''
Y luego, si no lo encuentra, lo intentará nuevamente sin el prefijo (el segundo elemento de la matriz es solo
*
que significa la importación inicial.
De esta forma, puede agregar carpetas adicionales para buscar archivos de declaración personalizados o incluso módulos
.ts
personalizados que desee poder
import
.
También puede crear asignaciones personalizadas para módulos específicos:
"paths" :{
"*": ["my-types", "some/custom/folder/location/my-awesome-types-file"]
}
Esto te dejaría hacer
import {MyType} from ''my-types'';
Pero luego lea esos tipos de
some/custom/folder/location/my-awesome-types-file.d.ts
Editar: fuera de fecha. Lee la respuesta anterior.
Todavía no entiendo esto, pero encontré una solución.
Use el siguiente
tsconfig.json
:
{
"compilerOptions": {
"target": "ES6",
"jsx": "react",
"module": "commonjs",
"sourceMap": true,
"noImplicitAny": true,
"experimentalDecorators": true,
"baseUrl": ".",
"paths": {
"*": [
"./typings/*"
]
}
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
Elimine
typings.json
y todo lo que se encuentre debajo de los
typings
carpeta, excepto
lodash.d.ts
.
También elimine todas las referencias
///...
Sé que esta es una vieja pregunta, pero las herramientas mecanografiadas han cambiado continuamente. Creo que la mejor opción en este punto es confiar en la configuración de ruta "incluir" en tsconfig.json.
"include": [ "src/**/*" ],
De manera predeterminada, a menos que realice cambios particulares, todos los archivos * .ts y * .d.ts en
src/
incluirán automáticamente.
Creo que esta es la forma más fácil / mejor de incluir archivos de declaración de tipo personalizados sin personalizar
typeRoots
y
types
.
Referencia:
"*": ["./types/*"]
Esta línea en las rutas tsconfig solucionó todo después de 2 horas de lucha.
{
"compilerOptions": {
"moduleResolution": "node",
"strict": true,
"baseUrl": ".",
"paths": {
"*": ["./types/*"]
},
"jsx": "react",
"types": ["node", "jest"]
},
"include": [
"client/**/*",
"packages/**/*"
],
"exclude": [
"node_modules/**/*"
]
}
tipos
es el nombre de la carpeta, que se encuentra junto a node_module, es decir, en el nivel de
la
carpeta del
cliente
(o carpeta
src
)
types/third-party-lib/index.d.ts
index.d.ts
ha
declare module ''third-party-lib'';
Nota: La configuración anterior es una configuración incompleta, solo para dar una idea de cómo se ve con los tipos, rutas, incluir y excluir en ella.