Làm thế nào để bạn tạo ra một tệp định nghĩa .d.ts kiểu đánh máy từ một thư viện JavaScript hiện có?


192

Tôi đang sử dụng rất nhiều thư viện cả bên thứ ba và bên thứ ba của mình. Tôi thấy thư mục "typings" chứa một số cho Jquery và WinRT ... nhưng chúng được tạo như thế nào?

Câu trả lời:


232

Có một vài tùy chọn có sẵn cho bạn tùy thuộc vào thư viện được đề cập, cách viết và mức độ chính xác mà bạn đang tìm kiếm. Chúng ta hãy xem xét các lựa chọn, theo thứ tự giảm dần.

Có lẽ nó tồn tại

Luôn luôn kiểm tra DefiniteTyped ( https://github.com/DefiniteTyped/DefiniteTyped ) trước. Đây là một repo cộng đồng với đầy đủ hàng ngàn tệp .d.ts và rất có thể thứ bạn đang sử dụng đã có sẵn. Bạn cũng nên kiểm tra TypeSearch ( https://microsoft.github.io/TypeSearch/ ) là công cụ tìm kiếm cho các tệp .d.ts do NPM xuất bản; điều này sẽ có nhiều định nghĩa hơn một chút so với DefiniteTyped. Một vài mô-đun cũng đang vận chuyển các định nghĩa của riêng họ như là một phần của phân phối NPM của họ, vì vậy cũng hãy xem liệu đó có phải là trường hợp trước khi cố gắng viết riêng của bạn không.

Có lẽ bạn không cần một

TypeScript hiện hỗ trợ --allowJscờ và sẽ tạo ra nhiều suy luận dựa trên JS trong các tệp .js. Bạn có thể thử bao gồm tệp .js trong phần tổng hợp của mình cùng với --allowJscài đặt để xem liệu điều này có cung cấp cho bạn thông tin loại đủ tốt hay không. TypeScript sẽ nhận ra những thứ như các lớp kiểu ES5 và các bình luận JSDoc trong các tệp này, nhưng có thể bị vấp nếu thư viện tự khởi tạo một cách kỳ lạ.

Bắt đầu với --allowJs

Nếu --allowJscho bạn kết quả tốt và bạn muốn tự viết một tệp định nghĩa tốt hơn, bạn có thể kết hợp --allowJsvới --declarationđể xem "dự đoán tốt nhất" của TypeScript tại các loại thư viện. Điều này sẽ cung cấp cho bạn một điểm khởi đầu tốt và có thể tốt như một tệp được viết bằng tay nếu các bình luận của JSDoc được viết tốt và trình biên dịch có thể tìm thấy chúng.

Bắt đầu với dts-gen

Nếu --allowJskhông hoạt động, bạn có thể muốn sử dụng dts-gen ( https://github.com/Microsoft/dts-gen ) để có điểm bắt đầu. Công cụ này sử dụng hình dạng thời gian chạy của đối tượng để liệt kê chính xác tất cả các thuộc tính có sẵn. Về mặt tích cực, điều này có xu hướng rất chính xác, nhưng công cụ chưa hỗ trợ loại bỏ các bình luận JSDoc để đưa vào các loại bổ sung. Bạn chạy như thế này:

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

Điều này sẽ tạo ra your-module.d.tstrong thư mục hiện tại.

Nhấn nút tạm dừng

Nếu bạn chỉ muốn làm tất cả sau và không cần gõ trong một thời gian, trong TypeScript 2.0 bây giờ bạn có thể viết

declare module "foo";

Nó sẽ cho phép bạn importcác "foo"mô-đun với loại any. Nếu bạn có một toàn cầu mà bạn muốn giải quyết sau này, chỉ cần viết

declare const foo: any;

Nó sẽ cung cấp cho bạn một foobiến.


25
Ouch ... đó sẽ là một rào cản đáng kể để nhập cảnh trong nhiều trường hợp. Sẽ thật tuyệt nếu có một công cụ có thể tạo ra ít nhất "dự đoán tốt nhất" dựa trên suy luận kiểu. Mặc dù những điều này có thể không tối ưu, nhưng ít nhất chúng có thể được điều chỉnh theo thời gian.
Hotrodmonkey

7
+1 - Tin tốt khác: --declarationstạo cả .jstệp và .d.tstệp, có nghĩa là bạn chỉ cần chạy một trình biên dịch.
Fenton

67
Có thể tìm thấy một bộ sưu tập các định nghĩa chất lượng cao cho các thư viện phổ biến tại github.com/borisyankov/DefiniteTyped
Boris Yankov

10
Công cụ 'dự đoán tốt nhất' sẽ không tốt hơn IntelliSense đã có trong TypeScript. Lợi ích của các định nghĩa kiểu là cung cấp nhiều thông tin hơn cho trình biên dịch hơn là nó có thể 'đoán'.
Boris Yankov

12
--allowJsvới --declarationcác tùy chọn không thể kết hợp (được thử nghiệm trong TypeScript 1.8 và 2.0). Nếu tôi thử, tôi nhận được:error TS5053: Option 'allowJs' cannot be specified with option 'declaration'
Alexey

52

Bạn có thể có thể sử dụng tsc --declaration fileName.tsnhư Ryan mô tả, hoặc bạn có thể chỉ định declaration: truedưới compilerOptionstrong của bạn tsconfig.jsongiả sử bạn đã có một tsconfig.jsonkhuôn khổ dự án của bạn.


4
Đây là câu trả lời tốt nhất nếu bạn đang phát triển mô-đun Angular 2 mà bạn muốn chia sẻ.
Darcy

Nếu tôi thử tsc --declaration test.tstôi gặp lỗi Cannot find name...cho các loại mà tôi đang cố gắng tạo tệp khai báo cho :) Vì vậy, tôi cần các loại trước khi tôi có thể khai báo chúng?
Kokodoko

2
@Kokodoko, bạn có thể thử thêm declaration: truevào tsconfig.jsontập tin của mình không?
JayKan

Cảm ơn, tôi chỉ muốn tạo * .d.ts từ * .ts.
vintproykt

16

Cách tốt nhất để giải quyết vấn đề này (nếu tệp khai báo không có sẵn trên DefiniteTyped ) là chỉ viết các khai báo cho những thứ bạn sử dụng chứ không phải toàn bộ thư viện. Điều này làm giảm công việc rất nhiều - và ngoài ra trình biên dịch có mặt để giúp đỡ bằng cách phàn nàn về các phương thức bị thiếu.


15

Như Ryan nói, trình biên dịch tsc có một công tắc --declarationtạo .d.tstệp từ .tstệp. Cũng lưu ý rằng (chặn lỗi) TypeScript được cho là có thể biên dịch Javascript, vì vậy bạn có thể chuyển mã javascript hiện có cho trình biên dịch tsc.


1
dường như hiện đang chuyển các tệp * .js vào tsc tạo ra lỗi "Lỗi đọc tệp" angular-resource.js ": Không tìm thấy tệp". Vì vậy, bạn phải đổi tên rõ ràng các tệp * .js thành * .ts để có thể sử dụng tsc. Thấy vấn đề này để biết thêm chi tiết - Tôi cố gắng sử dụng này trên angularjs: typescript.codeplex.com/workitem/26
James Strachan

3
từ những gì tôi có thể nói, tsc có thể biên dịch bất kỳ JavaScript hợp lệ nào, nhưng nếu nó không hợp lệ TypeScript (biên dịch đưa ra cảnh báo) thì cờ --declarations không xuất ra tệp .d.ts, vì vậy trừ khi thư viện của bạn được viết bằng TypeScript, bạn vẫn cần phải tự tạo tệp khai báo.
agradl


3

Dưới đây là một số PowerShell tạo một tệp định nghĩa TypeScript duy nhất một thư viện bao gồm nhiều *.jstệp với JavaScript hiện đại.

Đầu tiên, thay đổi tất cả các phần mở rộng thành .ts.

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

Thứ hai, sử dụng trình biên dịch TypeScript để tạo các tệp định nghĩa. Sẽ có một loạt các lỗi biên dịch, nhưng chúng ta có thể bỏ qua những lỗi đó.

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

Cuối cùng, kết hợp tất cả các *.d.tstệp thành một index.d.ts, loại bỏ các importcâu lệnh và loại bỏ defaultkhỏi mỗi câu lệnh xuất.

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 $_ }

Điều này kết thúc với một index.d.tstệp duy nhất, có thể sử dụng bao gồm nhiều định nghĩa.


2
Bước thứ hai, Get-ChildItem | foreach {tsc --declaration $ _. Name} đã hoạt động (đã thêm thiếu --declaration param)
Guru_07

3

Khi tạo thư viện của riêng bạn, bạn có thể tạo *.d.tstệp bằng cách sử dụng lệnh tsc(Trình biên dịch TypeScript) như sau: (giả sử bạn đang xây dựng thư viện của mình vào dist/libthư mục)

tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly
  • -d( --declaration): tạo các *.d.tstệp
  • --declarationDir dist/lib: Thư mục đầu ra cho các tệp khai báo được tạo.
  • --declarationMap: Tạo sơ đồ nguồn cho mỗi tệp '.d.ts' tương ứng.
  • --emitDeclarationOnly: Chỉ phát ra tệp khai báo '.d.ts'. (không có mã biên dịch)

(xem tài liệu cho tất cả các tùy chọn trình biên dịch dòng lệnh)

Hoặc ví dụ trong package.json:

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

và sau đó chạy: yarn build:types(hoặc npm run build:types)


Tôi vẫn không thể tìm ra cách tạo các d.tstệp và có thể sử dụng các giao diện. bạn có bất kì ví dụ nào không?
Danosaure

Kịch bản npm ở trên sẽ tạo các *.d.tstệp và đặt chúng vào dist/libthư mục. Bạn cần một tsconfig.jsontập tin trong thư mục gốc của dự án của bạn, nhưng dù sao thì nó cũng sẽ ở đó để dự án hoạt động.
magikMaker

Tôi không thể sử dụng chúng, một khi tiếp xúc. Tôi có bài đăng stackoverflow.com/questions/59742688 sau đây nếu bạn có thể làm cho nó hoạt động?
Danosaure

2

Tôi sẽ tìm một ánh xạ hiện có của các thư viện JS bên thứ 3 của bạn hỗ trợ Script # hoặc SharpKit. Người dùng của các trình biên dịch chéo C # sang .js này sẽ phải đối mặt với vấn đề mà bạn hiện đang gặp phải và có thể đã xuất bản một chương trình nguồn mở để quét lib bên thứ 3 của bạn và chuyển đổi thành các lớp C # của bộ xương. Nếu vậy hãy hack chương trình quét để tạo TypeScript thay cho C #.

Không, việc dịch giao diện công khai C # cho lib bên thứ 3 của bạn sang định nghĩa TypeScript có thể đơn giản hơn so với thực hiện tương tự bằng cách đọc JavaScript nguồn.

Sự quan tâm đặc biệt của tôi là khung ExtJS RIA của Sencha và tôi biết đã có các dự án được xuất bản để tạo ra một giải thích C # cho Script # hoặc SharpKit


FYI: Tôi vừa tạo tệp định nghĩa bản thảo đầu tiên cho Sencha / ExtJS: github.com/andremussche/extjsTypescript/blob/master/jsondocs/ trộm
André

Xin chào Trường hợp lạc đà, tôi đã lập một blog về việc sử dụng ExtJs với bản đánh máy: blorkfish.wordpress.com/2013/01/11/USE-extjs-with-typescript
blorkfish
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.