Come si produce un file di definizione "tipizzazioni" .d.ts da una libreria JavaScript esistente?


193

Sto usando molte librerie sia mie che di terze parti. Vedo che la directory "digitazioni" ne contiene alcune per Jquery e WinRT ... ma come vengono create?

Risposte:


232

Ci sono alcune opzioni disponibili per te a seconda della libreria in questione, come è scritta e quale livello di precisione stai cercando. Rivediamo le opzioni, in ordine decrescente di desiderabilità.

Forse esiste già

Controlla sempre per primo DefinitelyTyped ( https://github.com/DefinitelyTyped/DefinitelyTyped ). Questo è un repository di community pieno di migliaia di file .d.ts ed è molto probabile che la cosa che stai usando sia già lì. Dovresti anche controllare TypeSearch ( https://microsoft.github.io/TypeSearch/ ) che è un motore di ricerca per i file .d.ts pubblicati da NPM; questo avrà leggermente più definizioni di DefinitelyTyped. Alcuni moduli stanno inoltre spedendo le proprie definizioni come parte della loro distribuzione NPM, quindi vedi anche se è così prima di provare a scrivere le tue.

Forse non ne hai bisogno

TypeScript ora supporta il --allowJsflag e farà più inferenze basate su JS nei file .js. Puoi provare a includere il file .js nella tua compilation insieme --allowJsall'impostazione per vedere se questo ti dà informazioni sul tipo abbastanza buone. TypeScript riconoscerà cose come le classi in stile ES5 e i commenti JSDoc in questi file, ma potrebbe inciampare se la libreria si inizializza in modo strano.

Inizia con --allowJs

Se --allowJsti ha dato risultati decenti e si vuole scrivere un file di definizione meglio te stesso, è possibile combinare --allowJscon --declarationa vedere "ipotesi migliore" del dattiloscritto ai tipi di biblioteca. Questo ti darà un buon punto di partenza e potrebbe essere buono come un file creato a mano se i commenti di JSDoc sono ben scritti e il compilatore è stato in grado di trovarli.

Inizia con dts-gen

Se --allowJsnon ha funzionato, potresti voler usare dts-gen ( https://github.com/Microsoft/dts-gen ) per ottenere un punto di partenza. Questo strumento utilizza la forma di runtime dell'oggetto per enumerare con precisione tutte le proprietà disponibili. Tra i lati positivi, questo tende ad essere molto accurato, ma lo strumento non supporta ancora lo scraping dei commenti JSDoc per popolare altri tipi. Corri in questo modo:

npm install -g dts-gen
dts-gen -m <your-module>

Questo genererà your-module.d.tsnella cartella corrente.

Premi il pulsante Posticipa

Se vuoi solo fare tutto in seguito e andare senza tipi per un po ', in TypeScript 2.0 ora puoi scrivere

declare module "foo";

che ti permetterà importil "foo"modulo con il tipo any. Se hai un globale con cui vuoi occuparti in seguito, scrivi

declare const foo: any;

che ti darà una foovariabile.


25
Ahi ... questa sarà una barriera significativa per l'ingresso in molti casi. Sarebbe bello avere uno strumento in grado di produrre almeno "ipotesi migliori" basate sull'inferenza del tipo. Sebbene questi potrebbero non essere ottimali, potrebbero almeno essere sintonizzati nel tempo.
Tasto di scelta rapida

7
+1 - Ulteriori buone notizie: --declarationsgenera sia il .jsfile che il .d.tsfile, il che significa che è necessario eseguire solo una compilazione.
Fenton,

67
Una raccolta di definizioni di alta qualità per le biblioteche più diffuse è disponibile su github.com/borisyankov/DefinitelyTyped
Boris Yankov

10
Uno strumento "ipotesi migliore" non sarà migliore di IntelliSense già esistente in TypeScript. Il vantaggio delle definizioni dei tipi consiste nel fornire al compilatore più informazioni di quante ne possano "indovinare".
Boris Yankov,

12
--allowJscon le --declarationopzioni non possono essere combinate (testato in TypeScript 1.8 e 2.0). Se ci provo, ottengo:error TS5053: Option 'allowJs' cannot be specified with option 'declaration'
Alexey,

53

Puoi usare tsc --declaration fileName.tscome descritto da Ryan, oppure puoi specificare declaration: truesotto compilerOptionsnella tua tsconfig.jsonipotesi che hai già avuto un tsconfig.jsonsotto il tuo progetto.


4
Questa è la risposta migliore se stai sviluppando un modulo angolare 2 che desideri condividere.
Darcy,

Se provo tsc --declaration test.tsottengo l'errore Cannot find name...per i tipi per i quali sto cercando di creare un file di dichiarazione :) Quindi ho bisogno dei tipi prima di poterli dichiarare?
Kokodoko,

2
@Kokodoko, puoi provare ad aggiungere declaration: trueal tuo tsconfig.jsonfile?
JayKan,

Grazie, volevo solo generare * .d.ts da * .ts.
vintproykt

16

Il modo migliore per gestirlo (se un file di dichiarazione non è disponibile su DefinitelyTyped ) è scrivere dichiarazioni solo per le cose che usi piuttosto che per l'intera libreria. Questo riduce molto il lavoro - e inoltre il compilatore è lì per aiutarti lamentandoti dei metodi mancanti.


15

Come dice Ryan, il compilatore tsc ha un interruttore --declarationche genera un .d.tsfile da un .tsfile. Si noti inoltre che (escludendo i bug) TypeScript dovrebbe essere in grado di compilare Javascript, quindi è possibile passare il codice javascript esistente al compilatore tsc.


1
sembra attualmente passare file * .js in tsc genera un errore "Errore durante la lettura del file" angular-resource.js ": file non trovato". Quindi devi rinominare esplicitamente i file * .js in * .ts per poter usare tsc. Vedi questo problema per maggiori dettagli - Ho provato a usarlo su angularjs: typescript.codeplex.com/workitem/26
James Strachan,

3
da quello che posso dire, tsc può compilare qualsiasi JavaScript valido, ma se non è TypeScript valido (la compilazione fornisce avvisi), il flag --declarations non genera un file .d.ts, quindi a meno che la tua libreria non sia scritta in TypeScript tu è ancora necessario creare manualmente il file delle dichiarazioni.
agradl,


3

Ecco alcuni PowerShell che crea un singolo file di definizione TypeScript in una libreria che include più *.js file con JavaScript moderno.

Innanzitutto, modifica tutte le estensioni in .ts.

Get-ChildItem | foreach { Rename-Item $_ $_.Name.Replace(".js", ".ts") }

In secondo luogo, utilizzare il compilatore TypeScript per generare file di definizione. Ci saranno un sacco di errori del compilatore, ma possiamo ignorarli.

Get-ChildItem | foreach { tsc $_.Name  }

Infine, combina tutti i *.d.tsfile in uno index.d.ts, rimuovendo le importistruzioni e rimuovendo defaultda ciascuna istruzione di esportazione.

Remove-Item index.d.ts; 

Get-ChildItem -Path *.d.ts -Exclude "Index.d.ts" | `
  foreach { Get-Content $_ } | `
  where { !$_.ToString().StartsWith("import") } | `
  foreach { $_.Replace("export default", "export") } | `
  foreach { Add-Content index.d.ts $_ }

Questo termina con un singolo index.d.tsfile utilizzabile che include molte delle definizioni.


2
Secondo passo, Get-ChildItem | foreach { tsc --declaration $ _. Name} ha funzionato (aggiunto mancante --declaration param)
Guru_07

2

Vorrei cercare una mappatura esistente delle tue librerie JS di terze parti che supportano Script # o SharpKit. Gli utenti di questi cross-compilatori da C # a .js avranno affrontato il problema che ora affronti e potrebbero aver pubblicato un programma open source per scansionare la tua lib di terze parti e convertirla in classi di scheletro C #. In tal caso, hackerare il programma dello scanner per generare TypeScript al posto di C #.

In caso contrario, tradurre un'interfaccia pubblica C # per la tua libreria di terze parti in definizioni TypeScript potrebbe essere più semplice che fare lo stesso leggendo il codice sorgente JavaScript.

Il mio interesse speciale è il framework Extia RIA di Sencha e so che ci sono stati progetti pubblicati per generare un'interpretazione C # per Script # o SharpKit


Cordiali saluti: Ho appena creato il mio primo file di definizione dattiloscritto per Sencha / ExtJS: github.com/andremussche/extjsTypescript/blob/master/jsondocs/…
André,

hey Camel Case, ho creato un blog sull'uso di ExtJs con dattiloscritto: blorkfish.wordpress.com/2013/01/28/using-extjs-with-typescript
blorkfish

2

Quando crei la tua libreria, puoi creare *.d.tsfile usando il tsccomando (TypeScript Compiler) in questo modo: (supponendo che stai costruendo la tua libreria nella dist/libcartella)

tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly
  • -d( --declaration): genera i *.d.tsfile
  • --declarationDir dist/lib: Directory di output per i file di dichiarazione generati.
  • --declarationMap: Genera una mappa sorgente per ciascun file '.d.ts' corrispondente.
  • --emitDeclarationOnly: Emette solo file di dichiarazione '.d.ts'. (nessun JS compilato)

(consultare i documenti per tutte le opzioni del compilatore della riga di comando)

O ad esempio nel tuo package.json:

"scripts": {
    "build:types": "tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly",
}

e quindi esegui: yarn build:types(o npm run build:types)


Non riesco ancora a capire come generare i d.tsfile ed essere in grado di utilizzare le interfacce. Hai qualche esempio?
Danosaure

Lo script npm sopra genererà i *.d.tsfile e li inserirà nella dist/libcartella. Hai bisogno di un tsconfig.jsonfile nella radice del tuo progetto, ma dovrebbe essere lì perché il progetto funzioni comunque.
magikMaker

Non sono in grado di usarli, una volta esposti. Ho il seguente post stackoverflow.com/questions/59742688 se riesci a farlo funzionare?
Danosaure
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.