Typescript: Deklarasi tipe duplikat dengan link npm

Dibuat pada 15 Jan 2016  ·  147Komentar  ·  Sumber: microsoft/TypeScript

Menggunakan TypeScript 1.7.3.

Misalkan saya memiliki paket npm di bawah ini.
File deklarasi dihasilkan oleh compiler TypeScript, dan dirujuk dari paket lain dengan cara yang dijelaskan di sini .

paket-a

ts src:

export default class ClassA {
  private foo: string;
  bar: number;
}

deklarasi ts:

declare class ClassA {
  private foo;
  bar: number;
}
export default ClassA;

package-b (tergantung pada package-a):

ts src:

import ClassA from 'package-a';

namespace ClassAFactory {
  export function create(): ClassA {
    return new ClassA();
  }
}
export default ClassAFactory;

deklarasi ts:

import ClassA from 'package-a';

declare namespace ClassAFactory {
  function create(): ClassA;
}
export default ClassAFactory;

package-c (tergantung pada package-a dan package-b):

ts src:

import ClassA from 'package-a';
import ClassAFactory from 'package-b';

let classA: ClassA;
classA = ClassAFactory.create(); // error!!

Baris terakhir menyebabkan kesalahan selama kompilasi:

error TS2322: Type 'ClassA' is not assignable to type 'ClassA'.
Types have separate declarations of a private property 'foo'.

Ketika saya menghapus baris private foo; dari deklarasi package-a, TypeScript tidak mengeluarkan kesalahan apa pun.
Namun solusi ini agak menyakitkan.

Saya memahami bahwa mengekspos properti pribadi ke deklarasi adalah dengan desain (https://github.com/Microsoft/TypeScript/issues/1532).
Saya pikir TypeScript harus mengabaikan properti pribadi saat menyusun tugas variabel.
Atau apakah ada solusi yang lebih baik untuk ini?

@types Bug Fixed

Komentar yang paling membantu

Saya baru saja menggabungkan perubahan yang akan mencoba mendeteksi paket duplikat berdasarkan nama dan versinya, dan hanya menggunakan satu. Silakan mencobanya menggunakan typescript@next saat itu diterbitkan berikutnya.

Semua 147 komentar

Hanya ada satu deklarasi root ClassA sini, jadi kesalahan ini seharusnya tidak terjadi.

Maaf, saya menemukan bahwa ini terkait dengan npm link .

Ketika saya menggunakan npm link , paket diinstal seperti di bawah ini, karena ini hanya membuat tautan simbolik.

package-c
|
-- node_modules
    |
    -- package-a
    |   |
    |   -- index.d.ts
    |   |
    |   ...
    |
    -- package-b
        |
        -- index.d.ts
        |
        -- node_modules
        |   |
        |   -- package-a
        |       |
        |       -- index.d.ts
        |       |
        |       ...
        |
        ...

Seperti yang ditunjukkan, sepertinya ada dua file deklarasi berbeda untuk package-a.
Jika saya menginstal paket secara normal dengan menggunakan npm install , ini tidak terjadi karena deklarasi package-a tidak disertakan dalam package-b dalam kasus ini.

Saya berharap akan ada solusi untuk ini, tetapi mungkin sulit dan prioritas rendah.

Saya akhirnya tidak menggunakan npm link , dan ini tidak masalah lagi bagi saya.

Cukup adil, tetapi orang lain mungkin: mengedipkan mata:

sebenarnya ada dua file pada disk dengan dua deklarasi ClassA. jadi kesalahannya benar. tapi kita perlu mempertimbangkan modul node saat kita membandingkan tipe ini. masalah ini telah dilaporkan sebelumnya di https://github.com/Microsoft/TypeScript/issues/4800 , untuk Enums kami mengubah aturan menjadi pemeriksaan semi-nominal. mungkin melakukan hal yang sama untuk kelas.

Beri +1 pada ini dengan TS 1.7.5 dengan semua paket yang relevan yang terhubung dengan NPM. Saya mencoba membuat kasus percobaan yang menunjukkan masalah tersebut tetapi tidak bisa. Tidak peduli apa yang saya coba, TS baik-baik saja dengan skenario yang saya lihat gagal dengan TS2345 dalam aplikasi saya, dan sejauh yang saya tahu, semua salinan file .d.ts yang bermasalah adalah symlink ke file yang sama, jadi tidak boleh ada memiliki deklarasi berbeda dalam jenisnya. Akan lebih baik jika kesalahan yang dikeluarkan oleh Typecript mereferensikan file yang menyatakan dua tipe yang tidak kompatibel, karena itu mungkin menjelaskan sesuatu yang tidak saya pertimbangkan. Saat ini dikatakan ada dua definisi tetapi tidak melakukan apa pun untuk membantu pengembang menentukan masalahnya.

Sebagai solusinya, Anda dapat menggunakan <any> pada ekspresi yang bertentangan untuk melewati pemeriksaan tipe. Jelas ini mungkin mengharuskan Anda untuk melakukan anotasi jenis lain yang mungkin belum pernah Anda lakukan sebelumnya. Saya berharap seseorang dapat mengisolasi masalah ini di beberapa titik.

EDIT: memperjelas bahwa tautan NPM berperan dalam kasus saya

Melihat TS 1.8 tersedia, ditingkatkan dan masalah masih ada di versi itu juga.

Terima kasih untuk semua pekerjaan dalam menganalisis dan mendokumentasikan masalah ini. Kami mengalami masalah yang sama di beberapa basis kode kami. Kami mem-porting beberapa proyek untuk menggunakan dependensi package.json tetapi sekarang melihat ini ketika menggunakan npm link selama pengembangan.

Adakah yang bisa saya bantu untuk mengatasi masalah ini?

Saya menggunakan Lerna yang menautkan paket di sekitar dan melihat masalah di sana juga. Ketikan versi 2.0.3.

Sayangnya Lerna dan symlink-nya adalah persyaratan yang sulit, jadi saya menggunakan solusi buruk ini agar ini dapat dikompilasi dengan baik sementara masih dapat diperiksa jenisnya dengan benar oleh konsumen:

export class MyClass {
  constructor(foo: Foo) {
    (this as any)._foo = foo;
  }

  get foo() {
    return (this as any)._foo as Foo;
  }
}

Kelasnya sangat kecil jadi tidak terlalu sulit, dan saya tidak berharap itu benar-benar berubah, itulah sebabnya saya menganggap ini solusi yang dapat diterima.

FYI, saya juga berakhir di sini karena menggunakan npm link dan mendapatkan kesalahan ini. Adakah yang menemukan solusi untuk ini?

@xogeny dapatkah Anda menjelaskan lebih lanjut tentang bagaimana tautan npm menyebabkan masalah ini bagi Anda?

@mhegazy Saya mulai mendapatkan kesalahan ini seperti di atas (kecuali saya menggunakan Observable dari rxjs , yaitu, "Ketik 'Observable' tidak dapat ditugaskan untuk mengetik 'Observable'). Ini, tentu saja, tampak aneh karena dua saya mereferensikan Observable dari versi yang sama persis yaitu rxjs di kedua modul. Tetapi ketika tipe "bertemu", saya mendapat kesalahan. Saya menggali dan akhirnya menemukan masalah ini di mana @kimamula menunjukkan bahwa jika Anda menggunakan npm link , Anda akan mendapatkan kesalahan ini. Saya, seperti orang lain, mengatasi masalah ini (dalam kasus saya, saya membuat antarmuka duplikat dari hanya fungsi yang saya dibutuhkan dalam satu modul, bukan referensi rxjs ).

Apakah itu menjawab pertanyaan Anda? Saya bertanya karena menurut saya kasus saya tidak tampak berbeda dari yang lain di sini jadi saya tidak yakin apakah ini membantu Anda.

Kami telah melakukan pekerjaan di TS2.0 khusus untuk mengaktifkan skenario npm link (lihat https://github.com/Microsoft/TypeScript/pull/8486 dan # 8346). Apakah Anda memiliki contoh di mana saya dapat melihat di mana tautan npm masih tidak berfungsi untuk Anda?

Hah. Saya menjalankan 2.0.3 (saya sudah memeriksa). Saya akan mencoba membuat casing yang dapat direproduksi.

Omong-omong, Anda harus menindaklanjuti utas ini karena ini menyiratkan bahwa ini masih menjadi masalah pada TS 2.0:

https://github.com/ReactiveX/rxjs/issues/1858
https://github.com/ReactiveX/rxjs/issues/1744

Masalah yang saya lihat di repo Lerna saya agak terlibat, jadi saya membuat versi stripped-down di https://github.com/seansfkelley/typescript-lerna-webpack-sadness. Bahkan mungkin karena kesalahan webpack / ts-loader, jadi saya telah mengajukan https://github.com/TypeStrong/ts-loader/issues/324 ke sana juga.

Saya menggunakan skrip ketikan 2.0.3 dan saya melihat kesalahan ini dengan Observable seperti dijelaskan di atas, mis

Type 'Observable<Location[]>' is not assignable to type 'Observable<Location[]>'. Property 
            'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

Saya mendapatkan ini dalam paket Lerna monorepo juga. Rasanya seperti kebanyakan tetapi tidak semua bagian dari sistem tipe menggunakan realpath untuk mengidentifikasi file secara unik. Jika Anda melakukan perjalanan ke cabang yang menggunakan jalur symlink daripada jalur nyata, Anda akan mendapatkan tipe yang identik-tetapi-berbeda.

Ini adalah masalah yang cukup brutal yang hanya akan memengaruhi basis kode yang lebih kompleks, dan tampaknya tidak mungkin untuk menyelesaikannya tanpa mengambil tindakan drastis, jadi saya harap saya dapat meyakinkan Anda semua untuk memberikan perhatian yang layak. 😄

Ini paling terlihat dalam kasus di mana Anda memiliki aplikasi yang bergantung pada Dependensi A, Dependensi A bergantung pada Dependensi B dan menjual objek yang berisi tipe dari Dependensi B. Aplikasi dan Dependensi A keduanya npm link Dependensi B dan yang diharapkan dapat mengimpor jenis darinya dan meminta mereka menjelaskan hal yang sama.

Ini menghasilkan pesan kesalahan yang dalam, dan saya hampir menyelesaikan dan menghilangkan semua properti private dan protected di perpustakaan saya karena saya sudah kehilangan banyak waktu untuk ini :

TSError: ⨯ Unable to compile TypeScript
tests/helpers/test-application.ts (71,11): Argument of type '{ initializers: Initializer[]; rootPath: string; }' is not assignable to parameter of type 'ConstructorOptions'.
  Types of property 'initializers' are incompatible.
    Type 'Initializer[]' is not assignable to type 'Initializer[]'.
      Type 'Application.Initializer' is not assignable to type 'Application.Initializer'.
        Types of property 'initialize' are incompatible.
          Type '(app: Application) => void' is not assignable to type '(app: Application) => void'.
            Types of parameters 'app' and 'app' are incompatible.
              Type 'Application' is not assignable to type 'Application'.
                Types of property 'container' are incompatible.
                  Type 'Container' is not assignable to type 'Container'.
                    Types of property 'resolver' are incompatible.
                      Type 'Resolver' is not assignable to type 'Resolver'.
                        Types of property 'ui' are incompatible.
                          Type 'UI' is not assignable to type 'UI'.
                            Property 'logLevel' is protected but type 'UI' is not a class derived from 'UI'. (2345)

Sangat menghargai Anda semua yang melihat ini; Terima kasih!

@tomdale apakah Anda menggunakan Webpack, tsc atau alat pembuatan lainnya? Masalah saya tampaknya hanya terjadi ketika dikompilasi melalui Webpack (lihat repo tertaut dari komentar saya

@seansfkelley Sepertinya https://github.com/TypeStrong/ts-node.

Benar, ini menggunakan ts-node (untuk aplikasi root). Dependensi, bagaimanapun, adalah paket yang dikompilasi dengan tsc .

Saya baru saja mengalami masalah ini dan ini adalah masalah besar bagi kami karena kami menggunakan percobaan untuk membagi back end kami menjadi banyak perpustakaan kecil. Selama pengembangan, kami sering perlu npm menautkan repo kami. Masalah spesifik yang saya hadapi yang mendorong saya untuk menemukan ini adalah penggunaan rxjs Observables and interfaces:


// in repo A
export class HttpAdapter {
    request(url: string, options?: HttpRequestOptionsArgs): Observable<HttpResponse> {
        return Observable.of({});
    }
}

// in repo B
export class HttpRequestAdapter implements HttpAdapter {
    request(url: string, options?: HttpRequestOptionsArgs): Observable<HttpResponse> {
        return Observable.of({});
    }
}

Ini berfungsi jika saya tidak npm link , tetapi ketika saya melakukannya, saya mendapatkan:

Error:(10, 14) TS2420:Class 'HttpRequestAdapter' incorrectly implements interface 'HttpAdapter'.
  Types of property 'request' are incompatible.
    Type '(url: string, options?: HttpRequestOptionsArgs) => Observable<HttpResponse>' is not assignable to type '(url: string, options?: HttpRequestOptionsArgs) => Observable<HttpResponse>'.
      Type 'Observable<HttpResponse>' is not assignable to type 'Observable<HttpResponse>'.
        Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

Satu-satunya saran yang dapat saya buat adalah menghindari private . Saya tidak lagi mempublikasikan paket dengan private karena masalah ini dan hanya menggunakan prefiks bergaya JavaScript _ . Saya mengalaminya dengan https://github.com/Microsoft/TypeScript/issues/7755 yang merupakan diskusi serupa tentang mengapa private masuk ke sistem tipe nominal alih-alih struktural, dan karenanya melarangnya di sistem saya. memiliki proyek sendiri karena terlalu mudah untuk berakhir dengan perbedaan versi (Misalnya NPM 2 atau menggunakan npm link ).

@blakeembrey ketika Anda mengatakan hindari pribadi, apakah Anda menyarankan agar saya dapat mengubah sesuatu dalam kode saya? Saya berasumsi bahwa definisi tipe Observable adalah masalahnya, bukan?

@ jeffwhelpley Ya, maaf, Anda tidak salah. Itu Observable . Sayangnya, saran untuk menghindari private sangat tipis dan tidak sepenuhnya berlaku untuk Anda 😄 Mungkin Anda dapat mempermasalahkan, saya berasumsi, rxjs tentang penggunaan private di antarmuka publik mereka?

Sunting: Saya kebanyakan berkomentar karena saya telah mengikuti masalah sebelumnya dan menghindari bergabung dengan pengalaman saya sendiri, tetapi saya pikir saya juga dapat menuliskan pemikiran saya lagi, sebaliknya mereka mirip dengan https://github.com/Microsoft/TypeScript/issues/ 6496 # Issuecomment -255232592 (di mana @tomdale menyarankan untuk menghapus private dan protected , saya melakukan hal yang sama beberapa waktu lalu).

Saya mendapat kesan dari @mhegazy bahwa dia merasa tidak ada masalah dengan npm link . Tapi sepertinya masih mengganggu kita dan orang lain. Jadi saya tidak yakin di mana letak masalah ini? Apakah ini masalah yang diketahui dengan TS 2.0+ atau saya hanya melewatkan solusi di suatu tempat?!?

Saya mendapatkan masalah yang sama dan tampaknya bukan disebabkan oleh npm link . Saya masih mendapatkannya jika saya menginstalnya menggunakan npm install file.tar.gz . Inilah kesalahannya:

app/app.component.ts(46,5): error TS2322: Type 'Observable<boolean | Account>' is not assignable to type 'Observable<boolean | Account>'.
  Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

Inilah tampilan app.component.ts :

export class AppComponent implements OnInit {
  private user$: Observable<Account | boolean>;
  private loggedIn$: Observable<boolean>;
  private login: boolean;
  private register: boolean;

  constructor(public stormpath: Stormpath) {}

  ngOnInit() {
    this.login = true;
    this.register = false;
    this.user$ = this.stormpath.user$;
    this.loggedIn$ = this.user$.map(user => !!user);
  }

Ini mengeluh tentang baris this.user$ . Stormpath memiliki user$ didefinisikan sebagai berikut:

@Injectable()
export class Stormpath {

  user$: Observable<Account | boolean>;

@xogeny Aneh, pemahaman saya adalah identitas definisi terkait dengan lokasi file yang berarti mereka selalu akan menyebabkan masalah menggunakan npm link (karena ketergantungan npm link ed akan memiliki dependensinya sendiri yang diinstal) . Mungkin identitas definisi telah diubah - menggunakan hash file mungkin merupakan solusi yang baik di TypeScript. Sayangnya hanya ada selusin cara berbeda untuk berakhir dengan modul duplikat di JavaScript ( npm install dari GitHub, npm install , klon manual, konflik versi bahkan dapat mengakibatkan versi yang sama mendarat di lokasi berbeda karena bagaimana algoritma resolusi modul bekerja, dll).

@Mungkin . Tapi lalu tentang apa ini ?

Catatan, saya tidak mengeluh. Saya hanya mencoba mencari tahu apakah ada harapan untuk menyelesaikan ini atau tidak. Ini adalah duri yang serius di pihak kami karena semua alasan yang disebutkan @jeffwhelpley .

@xogeny Saya tahu, saya juga mencoba, saya ingin melihatnya diselesaikan dengan benar 😄 Saya membaca masalah yang ditautkan, tetapi semuanya dirancang untuk menyelesaikan jalur nyata dari symlink yang menyiratkan jika Anda memiliki dua file (asli) mereka masih akan bentrok karena akan menyelesaikannya di lokasi yang berbeda. Yang terjadi jika Anda npm link dari satu proyek ke proyek lain karena keduanya akan memiliki ketergantungannya sendiri yang dapat berbeda dengan simbol yang diekspor ulang dari paket npm link ed.

Sunting: Saya dapat mengonfirmasi, semua masalah adalah karena dua file. npm link akan memicunya karena sangat mudah untuk memiliki ketergantungan dalam repo yang baru saja Anda tautkan, yang merupakan ketergantungan yang sama seperti dalam proyek yang Anda tautkan. Repro sederhana akan melakukan npm install dari ketergantungan yang sama pada dua level aplikasi yang berbeda dan melihat kesalahan mereka.

image

Kepada siapa pun yang mengikuti utas ini ... Saya mencoba solusi yang dijelaskan di sini dan tampaknya berhasil (sejauh ini).

Saya telah mereproduksi kesalahan ini.

mkdir a; cd a
npm install rxjs
echo 'import * as rx from "rxjs"; export const myObservable: rx.Observable<number>;' > index.d.ts
echo '{ "name": "a" }' > package.json

cd ..; mkdir b; cd b
npm install rxjs
npm link ../a
echo 'import * as rx from "rxjs"; import * as a from "a"; const x: rx.Observable<number> = a.myObservable;' > index.ts
tsc index.ts --target es6 --moduleResolution node

Karena ada dua instalasi rxjs , kita mendapatkan:

index.ts(1,59): error TS2322: Type 'Observable<number>' is not assignable to type 'Observable<number>'.
  Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

saya memiliki solusi yang berfungsi baik untuk commandline, tetapi studio visual masih kacau: https://github.com/Microsoft/TypeScript/issues/11107#issuecomment -254003380

Solusi baru saya untuk Windows + Visual Studio 2015 adalah dengan merampok salinan xlib Library src dan dist folder ke dalam folder node_modules\xlib\src dan node_modules\xlib\dist dari proyek yang memakan.

berikut adalah bagian penting dari skrip file batch robocopy saya jika ada yang menginginkannya:

:rerunloop
    <strong i="14">@echo</strong> watching for changes to project files..............  (Ctrl-C to cancel)

    <strong i="15">@rem</strong> xlib --> blib and slib
    <strong i="16">@robocopy</strong> .\xlib\src .\blib\node_modules\xlib\src *.*  /MIR /NJH /NJS /NDL /XD .git
    <strong i="17">@if</strong> NOT "%errorlevel%" == "0" (
        <strong i="18">@rem</strong> copy occured, so copy both

        <strong i="19">@robocopy</strong> .\xlib\dist .\blib\node_modules\xlib\dist *.*  /MIR /NJH /NJS /NDL /XD .git   
        <strong i="20">@robocopy</strong> .\xlib\src .\slib\node_modules\xlib\src *.*  /MIR /NJH /NJS /NDL /XD .git     
        <strong i="21">@robocopy</strong> .\xlib\dist .\slib\node_modules\xlib\dist *.*  /MIR /NJH /NJS /NDL /XD .git

        <strong i="22">@rem</strong>  set the src dirs readonly
        <strong i="23">@attrib</strong> +R .\blib\node_modules\xlib\src\*  /S /D
        <strong i="24">@attrib</strong> +R .\slib\node_modules\xlib\src\*  /S /D
    )
    <strong i="25">@timeout</strong> /t 1 /nobreak > NUL
<strong i="26">@goto</strong> rerunloop

Maaf telah menyadap lagi dengan masalah ini, tetapi ini merupakan hambatan serius pada proyek kami karena tidak dapat melakukan npm link saat kami membuat perubahan. Saya akan sangat senang membantu dengan PR jika salah satu kontributor TypeScript saat ini dapat memberi saya sedikit panduan tentang di mana harus mulai mencari di basis kode.

Saya juga kesulitan dengan yang ini. Kami telah mengadopsi TS mulai dari aplikasi kecil, sekarang kami telah membaginya menjadi submodul dan menghubungkannya dan… BOOM. TS tidak dapat dikompilasi lagi. Apakah ini masih menjadi masalah di semua TS dist-tag? Saat ini saya mengalami ini di @rc (2.1.1).

@heruan dan @jeffwhelpley dapatkah Anda mencoba typescript@next , kami telah memperbaiki beberapa masalah terkait. dan jika Anda masih mengalami masalah, berikan informasi lebih lanjut tentang penyiapan proyek Anda.

@mhegazy Saya menggunakan Version 2.2.0-dev.20161129 dan masih mengalami masalah. Masalah spesifiknya adalah saya memiliki satu proyek (sebut saja ProjectA) yang berisi "antarmuka" (menggunakan kelas, tetapi saya dapat menggunakan kelas tersebut sebagai token untuk Angular 2 DI) sebagai berikut:

export class ServerAdapter {
    start(opts: ServerOptions): Observable<any> {
        return null;
    }
}

Kemudian dalam proyek yang benar-benar terpisah (sebut saja ProjectB) yang memiliki kelas yang mengimplementasikan antarmuka dari proyek pertama seperti ini:

export class RestifyServerAdapter implements ServerAdapter {
    start(opts: ServerOptions): Observable<any> {
        let server = restify.createServer();
        this.addPreprocessors(server);
        this.addRequestHandler(server, opts);
        return this.startServer(server, opts);
    }

   // more stuff here that is not relevant to this issue
}

Ketika saya melakukan kompilasi skrip jenis normal untuk ProjectB itu berfungsi dengan baik. Tetapi jika saya npm link ProjectA dari direktori root ProjectB dan kemudian menjalankan tsc lagi saya mendapatkan:

Types of property 'start' are incompatible.
    Type '(opts: ServerOptions) => Observable<any>' is not assignable to type '(opts: ServerOptions) => Observable<any>'. Two different types with this name exist, but they are unrelated.
      Type 'Observable<any>' is not assignable to type 'Observable<any>'. Two different types with this name exist, but they are unrelated.
        Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

Saya tidak dapat mereplikasi dalam proyek tiruan, saya rasa saya kehilangan penyebab masalah sehingga saya tidak dapat mereplikasi itu. @ jeffwhelpley dapatkah Anda menerbitkan proyek tiruan yang mereplikasi masalah? Saya pikir proyek Lerna harus bagus dan mudah diuji.

@heruan Saya akan mencoba mengaturnya.

Satu, FYI. Saya pikir saya mungkin telah menemukan jalan keluar. Masalah teratasi jika saya npm link rxjs di ProjectA dan ProjectB. Ini masuk akal karena dalam kasus itu, ProjectA dan ProjectB menggunakan file rxjs yang sama persis. Tanpa itu, mereka secara teknis menggunakan file yang berbeda (meskipun versinya sama):

Jika Anda hanya npm link ProjectA dari ProjectB, maka:

  • ProjectB mengarah ke node_modules / rxjs
  • ProjectA ada sebagai symlink di node_modules / ProjectA dan rxjs yang dirujuknya ada di node_modules / ProjectA / node_modules / rxjs

Tetapi jika Anda npm link rxjs di keduanya, maka kedua referensi rxjs tersebut akan dihubungkan ke lokasi npm global yang sama persis.

Bagaimanapun, ini jelas masih belum ideal, tapi setidaknya sesuatu yang bisa memajukan kita.

Juga ... tidak yakin apakah ini relevan atau penting (akan lihat setelah saya menyiapkan proyek uji), tetapi dua lib saya (yaitu ProjectA dan ProjectB) sebenarnya adalah repo npm pribadi.

Terima kasih @jeffwhelpley untuk petunjuknya, tetapi karena saya menggunakan Lerna semua modul sudah ditautkan satu sama lain sehingga mereka membaca file yang sama, tetapi saya pikir kompiler TS memperhitungkan jalur tautan dan bukan yang asli. Saya mungkin salah, karena saya tidak dapat mereproduksi proyek tiruan, dan saya benar-benar gila…

Adakah yang bisa menyelesaikan ini dengan cara yang elegan?

Juga, perhatikan bahwa ini bukan hanya masalah dengan npm link , Anda akan mendapatkan masalah ini juga pada build produksi, saat dependensi bersama Anda mengarah ke versi yang berbeda.

yaitu. ProjectA membutuhkan [email protected] dan ProjectB menggunakan [email protected]

Ketika Anda menginstal ProjectA sebagai ketergantungan di ProjectB, Anda juga akan memiliki tipe duplikat, karena misalnya akan ada dua deklarasi Observable , satu di node_modules/rxjs dan satu lagi di node_modules/project_a/node_modules/rxjs

Anda dapat menyiasatinya dengan mengizinkan versi rxjs di ProjectA menjadi seperti ~4.9.0 , sehingga npm install tidak perlu mengunduh versinya sendiri, dan sebagai gantinya akan menggunakan versi ProjectB. Namun perlu diingat bahwa ini bukan hanya masalah alur kerja pengembangan.

Posting di sini sebagai per @ andy-ms ini saran . Mencoba lagi kemarin dengan 2.0.x terbaru dan masih memilikinya.

Saya mendapatkan ini dengan pengetikan untuk Angular 1: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/10082#issuecomment -253023107

Mengalami hal ini lagi hari ini, khususnya masalah dengan symlink. Pengaturan saya adalah seperti ini:

node_modules/
folder
  another_folder
    node_modules/ (symlinked to ../../node_modules)
    app/ (angular1 app in typescript)
    tsconfig.json
    (other build files)

Jika saya hanya memiliki @types/angular , tsc . Jika saya memiliki seluruh rangkaian ( @types/angular-{animate,cookies,mocks,resource,route,sanitize} ) maka saya mulai mendapatkan banyak kesalahan jenis:

$ npm run tsc

> [email protected] tsc D:\work\angular.io\public\docs\_examples\upgrade-phonecat-1-typescript\ts
> tsc

../../node_modules/@types/angular/index.d.ts(17,21): error TS2300: Duplicate identifier 'angular'.
../../node_modules/@types/angular/index.d.ts(18,21): error TS2300: Duplicate identifier 'ng'.
app/app.animations.ts(5,3): error TS2339: Property 'animation' does not exist on type 'IModule'.
app/app.config.ts(6,45): error TS2305: Module 'angular' has no exported member 'route'.
app/core/checkmark/checkmark.filter.spec.ts(5,22): error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.
app/core/phone/phone.service.spec.ts(18,22): error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.
app/core/phone/phone.service.spec.ts(23,18): error TS2339: Property 'expectGET' does not exist on type 'IHttpBackendService'.
app/core/phone/phone.service.spec.ts(30,18): error TS2339: Property 'verifyNoOutstandingExpectation' does not exist on type 'IHttpBackendService'.
app/core/phone/phone.service.spec.ts(31,18): error TS2339: Property 'verifyNoOutstandingRequest' does not exist on type 'IHttpBackendService'.
app/core/phone/phone.service.spec.ts(39,18): error TS2339: Property 'flush' does not exist on type 'IHttpBackendService'.
app/core/phone/phone.service.ts(5,33): error TS2305: Module 'angular' has no exported member 'resource'.
app/phone-detail/phone-detail.component.spec.ts(5,22): error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.
app/phone-detail/phone-detail.component.spec.ts(18,46): error TS2305: Module 'angular' has no exported member 'route'.
app/phone-detail/phone-detail.component.spec.ts(20,20): error TS2339: Property 'expectGET' does not exist on type 'IHttpBackendService'.
app/phone-detail/phone-detail.component.spec.ts(32,20): error TS2339: Property 'flush' does not exist on type 'IHttpBackendService'.
app/phone-detail/phone-detail.component.ts(7,37): error TS2305: Module 'angular' has no exported member 'route'.
app/phone-list/phone-list.component.spec.ts(6,22): error TS2339: Property 'mock' does not exist on type 'IAngularStatic'.
app/phone-list/phone-list.component.spec.ts(15,20): error TS2339: Property 'expectGET' does not exist on type 'IHttpBackendService'.
app/phone-list/phone-list.component.spec.ts(26,20): error TS2339: Property 'flush' does not exist on type 'IHttpBackendService'.
node_modules/@types/angular-resource/index.d.ts(192,40): error TS2305: Module 'angular' has no exported member 'resource'.
node_modules/@types/angular/index.d.ts(17,21): error TS2300: Duplicate identifier 'angular'.
node_modules/@types/angular/index.d.ts(18,21): error TS2300: Duplicate identifier 'ng'.

Saya memperbaikinya dengan menambahkan basis ../../node_modules/@types sebagai typeRoots ke tsconfig.json :

    "typeRoots": [
      "../../node_modules/@types/"
    ]

Saya mencoba menambahkan node_modules/@types , tetapi tidak berhasil.

@heruan one hack yang mulai saya lakukan adalah menerapkan skrip npm saya sendiri untuk menautkan / membatalkan tautan daripada menggunakan fungsi lerna. Jadi, Anda dapat melakukan sesuatu seperti lerna run link dan kemudian di semua file package.json Anda memiliki skrip npm yang disebut link yang melakukan semua penautan npm termasuk (dalam kasus saya) npm link rxjs . Tampaknya berfungsi dengan baik, belum tentu tidak ideal.

@ jeffwhelpley dapatkah Anda membagikan solusi Anda di sini?

@yvoronen Saya tidak dapat membagikan semua kode saya, tetapi solusi saya dijelaskan di atas. Pada tingkat tinggi, kunci yang saya temukan adalah memastikan untuk menautkan npm tidak hanya semua proyek lokal yang Anda kerjakan, tetapi juga npm menautkan libs eksternal yang mungkin menyebabkan masalah (dalam kasus saya rxjs adalah masalah karena vars pribadi di objek Observable). Jadi, saya menggunakan lerna untuk mengelola semua proyek lokal saya dan kemudian menjalankan lerna run link . Di bawah layar ini memanggil npm run link dalam setiap folder akar proyek saya. Jadi, Anda harus memiliki skrip link ditentukan di package.json Anda seperti ini:

  "scripts": {
    "link": "npm link my-local-project1 && npm link my-local-project2 && npm link rxjs || true",
    "unlink": "npm unlink my-local-project1 && npm unlink my-local-project2 && npm unlink rxjs && npm i || true"
  }

Mudah-mudahan masuk akal, tapi beri tahu saya jika Anda memiliki pertanyaan.

Saya ingin memberikan pembaruan. Dari pertukaran tidak langsung yang saya lakukan dengan @mhegazy , inilah yang kami pikirkan.

  • Salah satu solusi yang kami pertimbangkan adalah konsep membedakan paket berdasarkan versi mereka serta nama resolusinya. Saya tidak memiliki detail lengkap tentang apa yang akan terlibat dalam hal ini.
  • Cara lainnya adalah dengan memperluas jalur sepenuhnya untuk mendapatkan identitas "sebenarnya" dari symlink. Saya percaya ini lebih sederhana, tetapi lebih terbatas ketika berurusan dengan paket yang sama di versi yang berbeda, tetapi membantu menyelesaikan sejumlah kasus yang layak.

Apakah Anda yakin komentar Anda termasuk dalam masalah ini? Kedengarannya benar-benar
berbeda.

Pada Kamis, 12 Jan 2017, 3:14 Nikos [email protected] menulis:

Catatan, saya tidak menggunakan tipe atau npm link AFAIK.

[image: image]
https://cloud.githubusercontent.com/assets/216566/21887548/451d059c-d8b8-11e6-86d1-50afae4e5c2f.png

-
Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment-272137732 ,
atau nonaktifkan utasnya
https://github.com/notifications/unsubscribe-auth/AAUAmcMXodOvU7coymMqGzTofD4pMagpks5rRgsogaJpZM4HFcWl
.

@dobesv sebenarnya adalah alasan utama mengapa Anda melihat masalah ini sejak awal. TypeScript mengenali deklarasi kelas sebagai dua deklarasi terpisah karena tidak dapat membedakan jalur yang terhubung dengan simbol dari jalur yang sebenarnya. Solusinya adalah dengan

  1. Perluas symlink.
  2. Periksa untuk melihat apakah paket berisi sama.

@DanielRosenwasser Maaf komentar saya adalah respon atas komentar orang lain "On Kam, 12 Jan 2017, 3:14 AM Nikos @ . * > Menulis" ... siapa itu dan apa yang mereka katakan Saya tidak ingat lagi, saya percaya mereka menanyakan tentang beberapa masalah di utas komentar ini, yang tidak ada hubungannya dengan tautan npm.

Tetapi sementara saya di sini, saya harus menyebutkan bahwa ada sesuatu yang lucu tentang cara nama file berperan dalam tipe. Hari ini saya memiliki masalah dengan RxJS di mana ia mengeluh bahwa metode ini-dan-itu tidak didefinisikan di Observable. Alasannya adalah bahwa pustaka HTTP memiliki salinan rxjs pribadinya sendiri yang berbeda dari orang lain. Nyatanya, saya menemukan empat salinan berbeda dari rxjs di pohon node_modules saya.

Ini tampaknya menjadi pendekatan bermasalah yang hanya akan terus bermasalah dan membingungkan.

Jika seluruh konsep nama file ini entah bagaimana berperan dalam identitas suatu tipe hilang, saya pikir masalah tautan npm ini akan hilang juga.

Saya masih agak bingung tentang cara kerjanya ... Saya baru mengenal TypeScript. Tapi kesan itulah yang saya dapatkan, adalah bahwa hal "nama file penting" ini telah menyebabkan saya cukup bingung sehubungan dengan perpustakaan yang saya gunakan (ionic2 dan angular2 dan rxjs).

Masalahnya adalah nama file tersebut masih merupakan identitas modul di Javascript, jadi tidak bisa hilang sepenuhnya. Dapatkah seseorang menjelaskan masalah apa yang terjadi dengan menggunakan jalur kanonik (resolusi symlink) yang berkaitan dengan beberapa versi paket? Jika ada beberapa versi paket dalam sebuah pohon, mereka akan memiliki beberapa jalur absolut kanonis, bukan?

EDIT: Saya menyadari ini setelah memposting, dan komentar ini merangkumnya dengan baik:
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -257016094

exclude dan compilerOptions.typeRoots sepenuhnya diabaikan oleh tsc. Saya mencoba semua kombinasi untuk mengabaikan jalur symlink, tetapi tidak mau
itu melihat modul sebagai jalur yang sama sekali berbeda, seperti itu menyelesaikan symlink dan tidak memahami pola yang dikecualikan.

misalnya, saya memiliki G:\www\cim-service-locator npm yang ditautkan dengan npm link cim-service-locator . di jalur proyek saya di G:\www\cim-backend , kesalahannya ditampilkan seperti ini:

crop

Saya mencoba segala kemungkinan kombinasi dari pengecualian / termasuk / tipeRoot tetapi tidak dapat membuat tsc mengabaikannya. menggunakan 2.2-dev.20170131

Kami mengalami masalah ini baik menggunakan "npm link" (melalui masalah SPFx yang dilaporkan oleh @waldekmastykarz) dan juga tanpa "npm link" (lihat bug # 11436).

Saya akhirnya menyadari bahwa keketatan compiler TypeScript disebabkan oleh ketidaksesuaian yang dapat terjadi secara realistis karena desain folder node_modules yang

A
+---B<strong i="8">@1</strong>
+---C
|   +---B<strong i="9">@2</strong>   <--- first copy of ClassB extends ClassE version 3.4
|   \[email protected]
+---D
|   \---B<strong i="10">@2</strong>   <--- second copy of ClassB extends ClassE version 3.5
\[email protected]

Dalam contoh ini, B @ 2 harus diinstal di subfolder untuk menghindari konflik dengan ketergantungan A 's di B @ 1 . Sekarang, misalkan ClassB meluas dari ClassE, dan kami memiliki sesuatu seperti ini:

B / package.json

{
  "name": "B",
  "version": "2.0.0",
  "dependencies": {
    "E": "^3.0.0",
    ...
}

Jika package.json C meminta [email protected] , maka dua salinan ClassB dapat berakhir dengan implementasi kelas dasar yang berbeda, yang berarti keduanya sebenarnya tidak kompatibel. Kode mungkin gagal saat runtime jika Anda mencoba menggunakannya secara bergantian.

Dalam contoh ini, TS2345 akan mencegah kesalahan itu, dan itu bagus. Namun, ini TIDAK penting: jika kompilator memperlakukan dua salinan KelasB sebagai setara, sistem tipenya akan tetap konsisten secara internal dan memiliki perilaku deterministik.

Ini penting karena bagi kami TS2345 kebanyakan menghasilkan alarm palsu. Alarm palsu ini memaksa orang untuk menulis "sebagai apapun" di mana pun mereka berbagi tipe di antara paket NPM, yang menyebabkan kesalahan lain. Jadi ketegasan menciptakan lebih banyak masalah daripada menyelesaikannya.

Saya ingin mengusulkan perbaikan berikut:

Jika SEMUA kondisi ini benar, maka JANGAN laporkan TS2345 untuk kelas dengan anggota pribadi:

  1. Tanda tangan publik kompatibel menurut tipe biasa TypeScript
  2. Kelas didefinisikan dalam folder paket NPM dengan nama dan versi yang sama (menurut package.json)
  3. Kelas memiliki jalur relatif yang sama untuk modul mereka (misalnya "./lib/blah/Bdts")

Jika salah satu kriteria ini tidak terpenuhi, maka tidak masalah untuk melaporkan TS2345.

@iclanton @ nickpape-msft

@seansfkelley Kesalahan Webpack dilacak oleh TypeStrong / ts-loader # 468

Hai kawan,
Seseorang menemukan solusi ??
Saya memiliki masalah yang sama ketika saya menautkan proyek dengan yang lain dengan RxJS.
Terima kasih;)

Hai, solusi sementara adalah membungkus Observable yang dikembalikan oleh dependensi dengan Observable#from .

Belum ada solusi. ?

Sepertinya ada dua masalah di sini.

Pengguna ts-loader mendapatkan kesalahan yang salah untuk definisi duplikat, tampaknya disebabkan oleh masukan yang tidak valid ke API kompilator. Perbaikan untuk itu tersedia di TypeStrong / ts-loader # 468.

Masalah lainnya adalah jika Anda memiliki paket yang sama (paket npm + versi yang sama) diinstal dua kali secara lokal pada sistem file (tidak menggunakan npm link ) dalam dua folder bersarang, dengan Enum atau kelas dengan anggota privat, membandingkan jenis dari dua paket ini akan gagal karena tidak kompatibel.
Masalah ini sedikit lebih terlibat dan akan membutuhkan pekerjaan tambahan bagi kompiler untuk "mendeduplikasi" paket sebelum memprosesnya.

Jika tidak satu pun dari kedua kategori ini sesuai dengan Anda, ajukan masalah baru dan berikan informasi yang cukup kepada kami untuk mereproduksi masalah secara lokal, dan kami akan dengan senang hati menyelidiki lebih lanjut.

Solusi yang diketahui adalah dengan menggunakan solusi multi-proyek yang akan menghilangkan folder duplikat, yaitu memastikan bahwa kedua subfolder node_modules berakhir dengan symlink ke target yang sama.

Rush (yang kami gunakan) dan Lerna adalah contohnya.

@smcatala Anda dapat menjelaskan solusi Anda. Saya perlu segera memperbaikinya. Terima kasih.

@ leovo2
modul 'foo':

import { Observable } from 'rxjs'
export function foo() {
  return Observable.of('foo')
}

kode klien di modul lain, yang bergantung pada modul 'foo':

import { Observable } from 'rxjs'
import { foo } from 'foo'

Observable.of(foo()) // wrap the returned Observable
.forEach(res => console.log(res))

@ leovo2708 solusi sederhananya adalah tidak menggunakan npm link .

menggunakan ts 2.1, saya telah dapat menggunakan tautan npm dengan satu perpustakaan (sebut saja xlib , yang merupakan contoh nyata saya) tetapi Anda harus memastikan bahwa modul perpustakaan Anda ( xlib ) beban tidak diduplikasi dalam folder node_modules proyek yang memakan.

Saya melakukan ini dengan alur kerja berikut

  1. hapus node_modules
  2. npm link xlib yang membuat sym_link ke xlib dalam proyek konsumsi saya node_modules
  3. npm install yang menginstal sisa dependensi proyek konsumsi saya

Saya belum benar-benar mengikuti percakapan ini atau memeriksa apakah masalah ini telah berubah / dimodifikasi sejak 2.2 tetapi saya akan membagikan solusi saya untuk ts 2.1

Jika itu berguna, saya mengumpulkan repro minimal dari beberapa definisi kasus enum di sini: https://github.com/rictic/repro-npm-link-typescript-issue

@mhegazy Kami melihat masalah di atas saat menggunakan tautan npm, meskipun menurut saya itu tidak memengaruhi sisa analisis Anda.

Terima kasih banyak, semoga segera diperbaiki. Namun, saya menggunakan solusi baru, duplikat file apa pun menggunakan Observable. Ini tidak bagus tapi hanya solusi sementara.

tsconfig.json menampilkan pemetaan jalur, tambahkan dependensi yang digandakan ke paths , sehingga akan dimuat dari kanan node_modules alih-alih yang ditautkan.

{
  "compilerOptions": {
    "baseUrl": ".", // This must be specified if "paths" is.
    "paths": {
      "@angular/common": ["../node_modules/@angular/common"],
      "@angular/compiler": ["../node_modules/@angular/compiler"],
      "@angular/core": ["../node_modules/@angular/core"],
      "@angular/forms": ["../node_modules/@angular/forms"],
      "@angular/platform-browser": ["../node_modules/@angular/platform-browser"],
      "@angular/platform-browser-dynamic": ["../node_modules/@angular/platform-browser-dynamic"],
      "@angular/router": ["../node_modules/@angular/router"],
      "@angular/http": ["../node_modules/@angular/http"],
      "rxjs/Observable": ["../node_modules/rxjs/Observable"]
    }
  }
}

Tidak yakin apakah sudah disebutkan di sini, tetapi solusi ini berhasil untuk saya: https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001

Ini pada dasarnya sama dengan solusi @charpeni di atas, kecuali tanpa awalan "../" di jalur. (yang tampak aneh, karena bukankah itu berarti file tsconfig.json akan berada di subfolder dari root proyek?)

Itu ide bagus @charpeni. Saya telah menggunakan pengaturan jalur itu untuk mengatasi berbagai masalah serupa lainnya, tetapi tampaknya juga ideal untuk yang satu ini. Faktanya, saya bertanya-tanya apakah pengaturan paths dalam proyek yang memakan (daripada dalam setiap proyek yang dikonsumsi) dapat mengganggu kompiler TypeScript dari resolusi node berikut. Jika berhasil, itu akan menjadi peretasan O (1), bukan peretasan O (n). Pada dasarnya skema seperti itu akan menjalankan resolusi node secara statis, kemudian memasukkan hasilnya ke dalam tsconfig.

Saya bereksperimen dengan hal-hal ini secara semi-publik jika ada yang ingin menonton (atau membantu ...). Saya mungkin akan mencoba ide di atas selanjutnya.

https://github.com/OasisDigital/many-to-many-angular

Untuk penggunaan yang lebih mudah, Anda juga dapat mengatur jalur seperti ini:

{
    "compilerOptions": {
        "baseUrl": ".", // This must be specified if "paths" is.
        "paths": {
            "@angular/*": ["../node_modules/@angular/*"],
            "rxjs/*": ["../node_modules/rxjs/*"]
        }
    }
}

npm link adalah bagian penting dari alur kerja saat bekerja dengan banyak paket sebagai lawan dari arsitektur mono-repo. TS harus dapat melihat bahwa kedua paket itu identik dan bukan kesalahan

@charpeni Saya tidak bisa mendapatkan solusi yang berfungsi. Untuk memperjelas, ke tsconfig.json mana ini harus ditambahkan? Paket root, atau paket terkait?

Saya juga mengalami masalah ini. Ini tiba-tiba mulai terjadi pada hari Senin, dan saya tidak yakin mengapa. Ini benar-benar menghambat pengembangan terutama dalam hal pengembangan paket untuk proyek kami. Saya telah mencoba berbagai solusi untuk memperbaikinya. Menjalankan mklink /j di Windows masih menyebabkan masalah ini terjadi, jadi ini bukan masalah tautan npm. Jika ada yang memiliki solusi atau perbaikan, ini akan sangat membantu.

Solusi saya adalah dengan npm menautkan setiap paket "duplikat" di paket root dan dependensi, karena kemudian mereka merujuk ke file yang sama lagi.

Btw, masalah ini tidak ada hubungannya dengan @types

Kami akhirnya menggunakan pola glob.

@felixfbecker Untuk implementasinya, tersedia di sini: https://github.com/sherweb/ng2-materialize/blob/master/demo-app/tsconfig.json#L19 -L22

Saya memiliki masalah serupa kecuali itu sepenuhnya terkait dengan @ types / node.

libA bergantung pada @ node / types
libB bergantung pada libA dan @ node / types
libC bergantung pada libA, libB, dan @ node / types

libA dibangun dengan baik.
libB npm ditautkan ke file build libA.
libC npm yang ditautkan ke libA dan libB gagal dalam pemeriksaan kesalahan seperti

libC/node_modules/@types/node/index.d.ts(102,6): Duplicate identifier 'BufferEncoding'.
libC/node_modules/libB/node_modules/@types/node/index.d.ts(102,6): Duplicate identifier 'BufferEncoding'.
libC/node_modules/libB/node_modules/libA/node_modules/@types/node/index.d.ts(102,6): Duplicate identifier 'BufferEncoding'.

Saya mencoba bermain-main dengan "types" dan "typeRoots" tetapi tidak berhasil.

@charpeni Sepertinya proyek Anda juga bergantung pada @ types / node. Apakah Anda memiliki wawasan tentang solusi untuk masalah atau solusi saya?

@nicksnyder yang mungkin karena versinya berbeda, dan @types/node adalah deklarasi global, artinya Anda tidak dapat menentukan nama yang sama dua kali. Inilah alasan mengapa yang terbaik untuk paket untuk _not_ bergantung pada pengetikan lingkungan, ini harus disediakan oleh pengguna:
https://github.com/Microsoft/types-publisher/issues/107

@nicksnyder Saya memiliki masalah serupa dan dapat mengatasinya dengan npm menghubungkan ketiga proyek ke satu @ types / node install. Karena definisi ditentukan dalam file yang sama, definisi tersebut tidak lagi duplikat

@felixfbecker Saya memverifikasi bahwa semua proyek bergantung pada versi node yang sama.

FWIW libA adalah https://github.com/Microsoft/vscode-languageserver-node/tree/master/jsonrpc , libB adalah https://github.com/Microsoft/vscode-languageserver-node/tree/master/client dan libC adalah ekstensi VS Code saya sendiri.

@uncleramsay bagaimana tepatnya Anda npm link @types/node ?

???
cd libA; npm link @types/node
cd libB; npm link @types/node
cd libC; npm link @types/node

Saya ingin melakukan solusi penautan, tetapi saya juga telah meretas ini dengan menghapus ketergantungan @ types / node di libA dan libB, dan menambahkan refs.d.ts yang berisi referensi lokal ke salinan node libC.

/// <reference path='../../../path/to/libC/node_modules/@types/node/index.d.ts'/>

Saya menemukan bahwa saya dapat menyelesaikan masalah yang saya alami dari deskripsi dalam komentar di https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -225303098

kami hanya menambahkan dukungan untuk resolusi symlink untuk modul ...

Di tempat terpisah di basis kode saat kami menggunakan dua gaya referensi berbeda:

/// <reference path="../node_modules/@types/library" />
/// <reference types="library" />

Keduanya tidak kompatibel dalam kasus di mana node_modules disambungkan, karena resolusi modul (dengan types= ) diperluas ke realpath, tetapi path= tidak. Ini menghasilkan dua file berbeda yang direferensikan ketika dikompilasi dengan tsc --listFiles , symlink dan realpath.

Solusi yang kami gunakan adalah menggunakan salah satu, tetapi tidak pernah keduanya. Ini juga membantu untuk menentukan typeRoots: [] di tsconfig untuk menghindari kompilator secara otomatis memuat tipe dari node_modules/@types dalam kasus menggunakan gaya reference path= .

Saya percaya preferensi ke depan (setidaknya bagi kami) adalah lebih memilih gaya types= .

Idealnya, memperluas ke realpath di reference path= akan lebih disukai, dan memeriksa duplikat jalur yang cocok untuk menghindari masalah seperti itu.

Harapan yang membantu seseorang.

@nicksnyder Anda harus dapat melakukan sesuatu seperti ini:

cd libA/node_modules/@types/node; npm link
cd libB; npm link @types/node
cd libC; npm link @types/node

Dengan cara itu, B & C menunjuk ke file yang sama persis dengan A.

@unclerams mungkin menyadari bahwa mereka semua adalah versi yang sama, yang mungkin belum pernah ada sebelumnya

Tidak bisakah dependensi peer menjadi solusi untuk ini?
http://codetunnel.io/you-can-finally-npm-link-packages-that-contain-peer-dependencies/

Dependensi peer diciptakan untuk situasi di mana plugin ingin menjelaskan kegunaannya. Mereka bekerja dengan baik untuk kasus itu. Tetapi mereka menyebabkan banyak masalah jika orang mulai mengubah semua dependensi mereka menjadi dependensi peer, berharap untuk menghindari duplikasi "npm install".

Kami menghabiskan waktu berbulan-bulan membuangnya dari repo git internal kami. Ketika digunakan seperti yang saya pikir Anda sarankan, dependensi rekan memungkinkan Anda untuk memecahkan masalah versi secara berdampingan dengan menukarnya untuk beberapa masalah baru:

  • seluruh pohon dibalik, yaitu setiap paket sekarang menjadi bertanggung jawab untuk mengambil ketergantungan keras pada paket yang dulunya merupakan ketergantungan tidak langsung, dalam banyak kasus tanpa tahu untuk apa itu

  • jika ketergantungan rekan dihapus, ketergantungan keras ini mungkin tidak akan pernah dihapus

  • pembuat paket tergoda untuk menggunakan rentang luas untuk pola versi sejenis mereka, mengklaim bekerja dengan versi yang sebenarnya tidak pernah mereka uji; bangunan rusak tiba-tiba menjadi masalah konsumen

Kata yang bagus.

solusi

Berikut adalah 3 opsi untuk solusi yang saya gunakan:

opsi 1: gunakan vscode bukan visual studio

Kompiler tsc jauh lebih pemaaf daripada VS2017, mungkin karena VS2017 merayapi kode (termasuk node_modules ) untuk menyediakan intellisense yang bagus dan dengan demikian menjadi bingung. Namun saya memiliki proyek multi-npm-modul besar yang kompleks jadi gunakan VS2017 ... jadi baca opsi 2 dan 3 untuk jika Anda memiliki kebutuhan serupa ....

opsi 2: keluarkan d.ts

jika Anda menggunakan outDir dan rootDir (dalam tsconfig.json ) modul lib-symlink Anda harus mengeluarkan d.ts deklarasi dan deklarasi tersebut harus ada di lib-module package.json types properti.

berikut adalah contoh tampilan lib-module tsconfig.json

{
  "compileOnSave": true,
  "compilerOptions": {
    "module": "commonjs",
    "sourceMap": true,
     "declaration": true,
    "jsx": "react",
    "newLine": "LF",
    "pretty": true,
    "stripInternal": true,
    "diagnostics": true,
    "target": "es5",
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src",
   //workaround for npm linking projects and associated dupe identifier bugs: https://github.com/Microsoft/TypeScript/issues/9566#issuecomment-287633339
    "baseUrl": "./",
    "paths": {
      "*": [
        "node_modules/@types/*",
        "*",
        "custom-dts/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

dan package.json lib-module Anda harus menyertakan sesuatu seperti berikut:

  "main": "./dist/_index.js",
  "types": "./dist/_index.d.ts",

Opsi ini berfungsi dengan baik, masalah utamanya adalah bahwa di studio visual saat debugging atau "go-to-definition" atau "show all reference", ini akan menunjukkan kepada Anda d.ts bukan file sumber skrip yang sebenarnya, yang mengalahkan manfaat utama studio visual (navigasi dalam proyek-proyek besar)

jika Anda ingin melihat contoh sebenarnya dari ini di alam liar, lihat modul npm xlib v8.5.x

opsi 3: keluarkan .js sebaris dengan sumber (pilihan favorit saya)

Anda dapat menggunakan file .ts secara langsung untuk mengetik di lib-modules yang terhubung! tetapi hanya jika Anda tidak menggunakan file outDir`` and rootDir in your tsconfig.json```. Itu akan membuat referensi VS2017 berfungsi dengan baik. Berikut adalah pengaturan konfigurasi yang Anda butuhkan:

{
  "compileOnSave": true,
  "compilerOptions": {
    "module": "commonjs",
    "sourceMap": true,
     //"declaration": true,
    "jsx": "react",
    "newLine": "LF",
    "pretty": true,
    "stripInternal": true,
    "diagnostics": true,
    "target": "es5",
    "moduleResolution": "node",
    "forceConsistentCasingInFileNames": true,
    //"outDir": "./dist",
    //"rootDir": "./src",
   //workaround for npm linking projects and associated dupe identifier bugs: https://github.com/Microsoft/TypeScript/issues/9566#issuecomment-287633339
    "baseUrl": "./",
    "paths": {
      "*": [
        "node_modules/@types/*",
        "*",
        "custom-dts/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

dan package.json lib-module Anda harus diubah menjadi:

  "main": "./src/_index.js",
  "types": "./src/_index.ts",

peringatan (hal-hal yang tidak akan berfungsi dengan opsi 3)

Solusi di atas hanya berfungsi jika setiap lib-module TIDAK memancarkan informasi tipe redundan. Misalnya saya dulu memiliki perpustakaan xlib mengekspos definisi tipe @types/async . Tapi kemudian saya memiliki perpustakaan lain yang juga secara independen mereferensikan @types/async . Menggunakan file .ts secara langsung untuk mengetik menyebabkan tsc mengimpor async dari dua modul lib, yang menyebabkannya muntah dengan berbagai bentuk masalah duplicate identifier . untuk mengatasi ini, Anda tidak perlu mengimpor @types dari beberapa modul lib, atau menggunakan opsi 2 .d.ts solusi

ringkasan

Semoga ini dapat menghemat waktu yang saya butuhkan .... Secara keseluruhan ini sangat menyakitkan, dan saya berharap tim ketikan dapat memperbaiki modul yang terhubung dengan sistem. Tapi setidaknya itu berfungsi sekarang (sebelum 2.x pada dasarnya tidak mungkin)

Solusi yang diposting oleh @mhegazy di https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001 (variasi solusi 2 @jasonswearingen) memecahkan masalah ini untuk kami saat menggunakan modul yang ditautkan dalam proyek lerna!

Saya hanya berpikir saya akan membagikan pengalaman saya ... mencoba membuat / mengekstrak lib dari proyek yang ada sehingga lib dapat dibagikan ke proyek lain.

Windows 10 Enterprise
Pembaruan VS 2015 3
Alat untuk VS2015 2.2.2
VS Kode 1.12.2
Ketikan 2.2.2
NPM: 3.10.9
Node: 6.9.2

Kami memiliki proyek ASP.MVC VS 2015 dengan front end Angular 4.1.x yang telah kami mulai mengekstrak beberapa komponen untuk membuat perpustakaan umum sehingga dapat digunakan dalam proyek lain.

Proyek perpustakaan dibangun menggunakan VS Code dan menggunakan rollup untuk membangun versi es2015, es5 dan umd ke dalam folder dist bersama dengan file d.ts yang sesuai.

Hasil akhirnya terlihat seperti ini:

-- dist
    |
    -- mylib
        |-- <strong i="16">@myscope</strong>
            |-- mylib.es5.js
            |-- mylib.js
        |-- bundles
            |-- mylib.umd.js
        |-- src
            |-- [all the d.ts folders/files]
        |-- index.d.ts
        |-- package.json
        |-- public_api.d.ts

Saya sudah npm menautkan folder dist / mylib ke folder ke proyek VS 2015 / Angular 4.1.x saya.

Ketika saya mencoba untuk mengkompilasi proyek di VS 2015, saya mendapatkan jenis pesan yang sama seperti yang dijelaskan dalam beberapa situasi di atas untuk Subscription, Observable, dll.

Ex: Build: Argument of type 'Subscription' is not assignable to parameter of type 'Subscription'.

Jika saya menghapus sementara direktori node_modules dari proyek perpustakaan, saya mendapatkan kesalahan baru yang mengeluh karena tidak dapat menemukan modul:

ex: Build: Cannot find module 'rxjs/Observable'.

Yang membawa saya pada kesimpulan bahwa ketika compiler skrip mengkompilasi aplikasi itu memang terlihat di folder node_modules dari paket perpustakaan saya yang tertaut untuk definisi modul untuk perpustakaan saya dan bukan folder aplikasi node_modules.

Tidak jelas bagi saya solusi mana yang diusulkan di atas yang akan memberikan solusi untuk masalah ini, dapatkah seseorang membantu saya?

Terima kasih!

@mikehutter Dalam proyek Anda yang menggunakan perpustakaan Anda (bukan di perpustakaan itu sendiri), lakukan sesuatu seperti ini di tsconfig Anda:

    "paths": {
      "rxjs/*": ["../node_modules/rxjs/*"]
    },

Anda mungkin memerlukan sedikit penyesuaian untuk ini tergantung di mana tsconfig dan kode sumber Anda dihasilkan.

(Seperti orang lain di utas ini, saya ingin melihat beberapa peningkatan TypeScript yang membuat ini tidak perlu.)

@mikehutter baru-baru ini kami menambahkan beberapa panduan di CLI Angular untuk bekerja dengan lib yang tertaut, dan sepertinya dalam kasus Anda, Anda kehilangan konfigurasi jalur TypeScript untuk RxJ di aplikasi konsumen Anda. Lihat https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/linked-library.md untuk info lebih lanjut.

@kylecordes ada di poin 👍

Terima kasih @kylecordes dan @filipesilva! Hanya itu yang saya butuhkan ...

Hai!

@mhegazy , apakah Anda yakin ini akan mencapai 2,4 atau kemungkinan besar akan ditunda lagi?
Ini sangat menyakitkan untuk mengatasinya, memaksa setiap proyek untuk selalu mendefinisikan pemetaan jalur untuk hal-hal yang seharusnya tidak mereka pedulikan.

Sangat berharap kali ini berhasil rilis!

Terbaik,

Jangan berpikir ini telah disebutkan, tetapi cara cepat untuk mengatasi masalah ini adalah:

{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "*": ["node_modules/*", "*"]
        }
    }
}

Entri paths atas pada dasarnya mengatakan: untuk modul apa pun, pertama-tama cari di folder node_modules di root proyek, lalu kembali ke aturan normal (berjalan secara rekursif ke direktori dari mana impor telah terjadi).

(Harap perbaiki saya jika saya salah, saya masih relatif pendatang baru di TS).

Entri di paths tampaknya terkait dengan baseUrl . Jadi, jika Anda menyetel baseUrl menjadi subfolder, Anda perlu mengubah definisi jalur yang sesuai. Misalnya:

{
    "compilerOptions": {
        "baseUrl": "./src",
        "paths": {
            "*": ["../node_modules/*", "*"]
        }
    }
}

@fiznool fyi itu bagian dari solusi saya opsi 2 dan 3 (di posting saya di atas). Saya telah melihat bahwa hanya menyetel properti paths tidak cukup jika Anda memiliki proyek symlink yang menggunakan pengetikan yang sama.

@jasonswearingen posting Anda jauh lebih komprehensif daripada saya ... terima kasih telah menyelesaikannya. Saya pasti akan merujuk kembali jika saya mengalami masalah lagi. 😄

Kami juga melihat ini di proyek Google. Seperti yang dijelaskan di sini:
https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -306969543

Solusi yang dijelaskan di atas menggunakan baseUrl dan jalur tampaknya tidak berfungsi, tsc masih mengambil definisi duplikat dan tidak ada kombinasi jalur / baseUrl / include / exclude / etc. telah mampu meyakinkannya sebaliknya.

Saya ingin tahu bagaimana ini bekerja secara normal, jika Anda memiliki proyek yang bergantung pada X, dan juga bergantung pada Y yang secara transitif bergantung pada X, bagaimana tsc menghindari memuat definisi tipe dua kali?

@esprehn Saya sangat menyarankan Anda membaca posting solusi saya di sini: https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -302886203

mengenai tautan itu, kedua solusi saya (2 dan 3) membutuhkan lebih dari sekadar pengaturan baseUrl dan jalur, jadi jika hanya itu yang Anda lakukan, silakan baca kembali. cara "mudah" adalah solusi 2, tetapi preferensi saya adalah solusi 3 karena memungkinkan "navigasi ke definisi" yang tepat melalui studio visual. Masalah dengan solusi 3 adalah Anda hanya perlu memuat definisi eksternal .d.ts sekali dalam rantai ketergantungan.

semoga membantu.

+1 Saya menggunakan lerna dan subdependensi dengan pengetikan yang disertakan ditandai sebagai "duplikat" saat disertakan melalui dependensi yang ditautkan.

Saya dapat membagikan kode jika diperlukan.

Dengan WebPack seperti di Angular-CLI, minta Angular-CLI package.json mereferensikan paket RXJS , lalu hapus paket `RXJS 'dari package.json proyek lain yang tidak Anda perlukan karena WebPack .

Situasi ini mungkin terjadi tidak hanya dengan symlink, tetapi dengan npm-shrinkwrap.json dalam ketergantungan dengan @types/node dalam dependencies . Shrinkwrap membuat npm menginstal dua versi identik @types/node ke dalam paket induk dan ke dalam yang menyusut. Silakan lihat https://github.com/KingHenne/custom-tslint-formatters/issues/5

Juga mengalami hal ini saat menggunakan proyek react yang memasang @types/react dan menautkannya ke aplikasi yang juga menggunakan @types/react

Saya mengalami masalah yang sama saat bekerja dengan paket dengan yarn link .
Rx.js melakukan kesalahan: Type 'Observable<Location[]>' is not assignable to type 'Observable<Location[]>'. Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'

Untungnya, saya telah menyelesaikannya dengan menggunakan versi Rxj.s di paket induk dan tertaut.
Jadi, dalam kasus saya, dua versi berbeda dari Rx.js menyebabkan masalah.

Ini adalah pemblokir besar saat bekerja dengan monorepos. Sangat berharap ini tidak akan lagi tertunda dan menemukan jalannya ke 2.5.

Edit: 😮

image

Menarik. Monorepo adalah satu skenario di mana tim saya TIDAK mengalami masalah ini, karena symlink mengarahkan semuanya kembali ke folder paket umum.

Tim saya sering mengalami masalah ini saat menautkan perpustakaan internal kami sendiri selama pengembangan.

Baru-baru ini kami menemukan alat bernama yalc yang meringankan ini dengan sangat baik dan benar-benar membuat perulangan dev yang cukup bagus. (Sebagai tl; dr alih-alih menautkan seluruh paket, ia menjalankan skrip prapublikasi dan menyalin hasilnya ke folder yang ditautkan).

Masalah ini sepertinya terus-menerus dimundurkan. Karena ini benar-benar mengganggu alur kerja banyak orang, mungkinkah kami memiliki semacam perbaikan sementara, seperti 'nonaktifkan komentar' seperti yang disarankan di # 9448?

import { baz$ } from './qux';
function foo (bar$: Observable<any>) {}

foo(baz$);
> Duplicate identifier

// Makes foo's `bar$` type equal to that of `baz$`
foo(/*typescript:identicalIdentifier*/ baz$);

"Nonaktifkan komentar" tidak jauh lebih baik daripada hanya melakukan gips di mana-mana, yang cukup menyakitkan dalam proyek besar. Di atas saya mengusulkan perubahan kompiler berikut:

Jika SEMUA kondisi ini benar, maka JANGAN laporkan TS2345 untuk kelas dengan anggota pribadi:

  1. Tanda tangan publik kompatibel menurut tipe biasa TypeScript
  2. Kelas didefinisikan dalam folder paket NPM dengan nama dan versi yang sama (menurut package.json)
  3. Kelas memiliki jalur relatif yang sama untuk modul mereka (misalnya "./lib/blah/Bdts")

Jika salah satu kriteria ini tidak terpenuhi, maka tidak masalah untuk melaporkan TS2345.

Perbaikan yang disederhanakan juga masih akan lebih baik daripada situasi saat ini, misalnya hanya mempertimbangkan # 1, mungkin hanya jika orang memilih melalui tsconfig. Ini seharusnya cukup murah untuk diterapkan.

Pendekatan ini memiliki keuntungan hanya dengan menonaktifkan alarm palsu, tetapi mempertahankan semantik yang ada. Sedangkan node_modules remapping hacks mengubah resolusi modul NPM dengan cara yang mungkin salah (misalnya menyebabkan kode tidak berfungsi dalam contoh hipotetis yang saya berikan ).

Sejujurnya, saya bahkan tidak yakin apakah ini harus "diperbaiki" di Typecript, karena ada juga masalah dengan JavaScript biasa: Operator instanceof akan mengembalikan false jika kelas objek berbeda dari kelas yang disediakan.

Jadi, saya lebih suka menantikan alternatif yang lebih baik untuk tautan npm yang mungkin menghubungkan ke require (), terlebih dahulu.

Itu wawasan yang bagus. Sudahkah Anda melihat pnpm ? Ini adalah langkah maju kecil dari desain node_modules saat ini, tetapi sangat efektif jika saya memahaminya dengan benar.

Ini bukan hanya tentang npm link yang dapat diganti atau tidak digunakan, tetapi tentang memiliki beberapa versi paket @types/xxx yang sama yang diinstal pada saat yang sama, sering kali ditarik dari dependensi yang menyediakan deklarasi TypeScript yang bergantung pada deklarasi standar, seperti yang saya dan orang lain laporkan. Jumlah paket seperti itu akan bertambah dengan lebih banyak adopsi TypeScript di komunitas Node.

@Yogu Saya pikir itu membingungkan identitas dan kesetaraan. Meskipun impor paket / versi yang sama dari dua lokasi mungkin mewakili dua contoh jenis yang berbeda, keduanya tetap sama dalam jenisnya.

Kode berikut (valid) muncul di benak:

type a = { c: string };
type b = { c: string };

function foo (bar: a) {}

const baz: b = { c: 'd' };
foo(baz);

Hal yang sama harus diterapkan untuk perpustakaan yang kita impor.

Jenis yang diimpor dari versi perpustakaan yang berbeda (dan paket @types ) bisa sama dan berbeda (jika perpustakaan diperbarui, definisi jenis harus diperbarui juga untuk mencerminkan perubahan).

Saya baru saja menggabungkan perubahan yang akan mencoba mendeteksi paket duplikat berdasarkan nama dan versinya, dan hanya menggunakan satu. Silakan mencobanya menggunakan typescript@next saat itu diterbitkan berikutnya.

Hore, terima kasih banyak karena sudah memperbaikinya! :-)

@pgonzal Terima kasih atas penunjuk ke pnpm, ini pasti terlihat menarik!

@sompylasar @types/node adalah kasus khusus, tetapi untuk @types/react , inilah saran saya: Masukkan semua dependensi yang diperlukan untuk API modul ke dalam peerDependencies , tidak menjadi dependencies . Ini memperjelas bahwa versi dependensi harus cocok (atau setidaknya kompatibel) antara modul induk dan anak. Jika orang tua dan anak sama-sama menggunakan react tetapi tidak bertukar objek tipe react, masalah ini tidak akan muncul di tempat pertama.

@harangue Jika sebuah kelas dideklarasikan dua kali dalam dua file berbeda, dengan nama yang sama dan struktur yang sama, masih ada dua kelas berbeda yang tidak dianggap sama oleh JavaScript. Seperti yang saya sebutkan, operator instanceof masih akan membedakan instance dari dua kelas.

Lihat biola ini untuk demonstrasi.

Itulah alasan saya lebih suka menyelesaikan ini pada level NPM (jadi kami tidak memiliki banyak deklarasi jika itu tidak dimaksudkan) daripada di TypeScript.

@Yogu : +1: jadi jika @types/node adalah kasus khusus, yaitu Anda tidak dapat menjalankan program menggunakan dua versi node yang berbeda pada saat yang sama, itu akan menjadi satu versi, dan kemungkinan besar yang ditentukan di paket tingkat atas, mungkin TypeScript harus memperlakukannya sebagai kasus khusus, misalnya selalu menggunakan tingkat atas @types/node untuk setiap ketergantungan?

@ andy-ms Terima kasih untuk ini!

Silakan mencobanya menggunakan skrip ketikan @ next ketika itu diterbitkan berikutnya.

Saya berasumsi itu belum terjadi. Saya sudah mencobanya dengan beberapa proyek tetapi sejauh ini tidak berhasil. Akan sangat menyenangkan melihat pembaruan di utas ini segera setelah next tersedia. @ andy-ms

Sepertinya pembangunan harian telah berhenti lagi. Yang terakhir adalah: 2.5.0-dev.20170808 .

cc / @DanielRosenwasser

Saya tidak yakin apakah ini terkait, tetapi ketika mencoba 2.5.1 saya tampaknya hanya melihat satu aspek dari sebuah modul, bahkan ketika modul tersebut telah memperluas d.ts di tempat lain.

jika saya memiliki @types untuk sesuatu katakanlah @types/mongodb dan saya memiliki deklarasi kustom yang memperluas modul itu, yaitu menambahkan janji ke metode, jadi saya sekarang memiliki @types/mongodb yang memiliki modul mongodb dan saya memiliki file d.ts dalam proyek saya yang disebut sesuatu seperti mongo-promisification.d.ts yang berisi modul mongodb .

Jadi dengan skenario di atas saya memiliki file yang memiliki import {somethingFromTypes} from "mongodb" itu mengeluh bahwa data dari modul jenis tidak dapat ditemukan, meskipun itu ada dan valid, tetapi jika saya melakukan import {somethingFromMyExtendingDts} from "mongodb" itu berfungsi baik.

Ketika mengkompilasi saya baru saja diberitahu bahwa modul tidak mengekspor barang itu, ketika itu terjadi, begitu juga perilaku yang diinginkan ini dan saya hanya perlu mengekspor ulang pada d.ts kustom saya atau haruskah itu mengambil kedua jenis dan ekstensi d.ts Saya sudah?

Saya menjalankan uji coba terbaru (Windows 10 64 bit) dan ini tampaknya tidak diperbaiki untuk saya.

Reproduksi

Struktur

a/
  index.ts
  package.json
b/
  index.ts
  package.json

Lari

cd a
npm link
cd ../b
npm link a

a / index.ts

import { Observable } from 'rxjs/Observable';

export class Foo {
  public bar: Observable<any>;
}

b / index.ts

import { Foo } from '@rxjs-test/a';
import { Observable } from 'rxjs/Observable';

const baz = new Foo();

function qux (quux: Observable<any>) {}

// TypeError
qux(baz.bar);

Lari

b>tsc -v
Version 2.6.0-dev.20170826

b>tsc index.ts
index.ts(11,5): error TS2345: Argument of type 'Observable<any>' is not assignable to parameter of type 'Observable<any>'.
  Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.

@ Untung Saya pikir masalah dalam situasi Anda adalah bahwa Anda memiliki dua deklarasi modul, di mana yang Anda butuhkan adalah modul dan augmentasi.
Anda harus dapat melakukan mongo-promisification.d.ts seperti ini:

import * as mongodb from "mongodb"; // import the real mongo

// now augment it
declare module "mongodb" {
    // new stuff...
}

Tanpa import , Anda berada dalam konteks ambient dan menulis deklarasi baru, bukan augmentasi.

( Buku Pegangan ref)

Dapat mengonfirmasi bahwa ini berfungsi untuk saya sekarang dengan [email protected] . Terima kasih banyak kepada @ andy-ms - ini adalah pengubah permainan!

Saya memiliki masalah yang sama, ketika saya mengimpor Observablemelalui pustaka Typecript ke proyek angular-cli dan fungsinya menggunakan potongan kode

function getitems (): Dapat diamati
http.get (). map (respon: Respon) => {
kembaliresponse.json ();
}


and when I removed the Observable<T> from function getitems() to not return anything the error disappear.
```function getitems()
http.get().map(response : Response) =>{
return <T> response.json();
}

@ Basel78 Saya memerlukan contoh lengkap untuk dapat mereproduksi kesalahan Anda. Selain itu, pastikan Anda menggunakan typescript@next - angular-cli mungkin menggunakan versi lama yang tidak memiliki fitur deduplikasi.

Saya sudah mencoba [email protected] tetapi masih mendapatkan banyak kesalahan TS2300: Pengenal duplikat.
Sayangnya saya tidak dapat membagikan keseluruhan proyek. Tapi inilah beberapa detailnya:
tsconfig paket npm-link-ed:

    "compilerOptions": {
        "module": "amd",
        "target": "es3",
        "sourceMap": true,
        "noEmitHelpers": true,
        "experimentalDecorators": true,
        "baseUrl": ".", // This must be specified if "paths" is.
        "paths": {
            "lib/*": [ "src/lib/*" ],
            "modules/*": [ "src/modules/*" ],
            "vendor/*": [ "src/vendor/*" ]
        },
        "typeRoots" : ["src/typings"]
    },
    "include": [
        "src/**/*.ts",
        "src/**/.*.ts", // TS ignores file names starting with dot by default
        "tests/**/*.ts",
        "tests/**/.*.ts"
    ]

tsconfig proyek utama ( @croc/webclient adalah paket tertaut):

    "extends": "./node_modules/@croc/webclient/tsconfig",
    "include": [
        "src/**/*.ts",
        "src/**/.*.ts",
        "node_modules/@croc/webclient/src/**/*.ts",
        "node_modules/@croc/webclient/src/**/.*.ts"
    ],
    "compilerOptions": {
      "baseUrl": ".",
      "typeRoots" : ["node_modules/@croc/webclient/src/typings"],
      "paths": {
        // map runtime paths to compile-time paths
        "lib/*": [ "node_modules/@croc/webclient/src/lib/*" ],
        "modules/*": [ "node_modules/@croc/webclient/src/modules/*" ],
        "vendor/*": [ "node_modules/@croc/webclient/src/vendor/*" ]
      }
    }

@ evil-shrike dapatkah Anda mengurangi proyek Anda menjadi contoh sederhana yang menunjukkan masalah tersebut?

@mhegazy ini dia
https://github.com/evil-shrike/typescript-npmlink-issue
di root propject:

cd lib
npm link
cd ../main
npm link tstest-lib

lalu di main :

npm run tsc

Hai @ evil-shrike, saya telah mempersempit masalah menjadi:
lib / tsconfig.json

{
    "compilerOptions": {
        "typeRoots" : ["src/typings"]
    }
}

main / tsconfig.json

{
    "extends": "./node_modules/tstest-lib/tsconfig",
    "include": [
        "node_modules/tstest-lib/src/**/*.ts"
    ]
}

Jadi kami akhirnya memasukkan keduanya (dari tsc --listFiles ):

/main/node_modules/tstest-lib/src/typings/jquery/index.d.ts
/lib/src/typings/jquery/index.d.ts

Karena node_modules berasal dari include dan bukan dari resolusi modul, saya rasa kita tidak menyebut realpath di atasnya, jadi itu berakhir sebagai dua file yang disertakan berbeda.
Yang terbaik adalah tidak menyertakan node_modules , dan sebagai gantinya mengkompilasinya secara terpisah dan mengimpornya seperti yang Anda lakukan pada paket eksternal lainnya.

@ andy-ms
Tidak mudah melakukannya. Lib yang direferensikan dalam kasus saya memiliki banyak ambient d.ts yang misalnya memperluas antarmuka global. Seperti JQueryStatic:

interface JQueryStatic {
    cleanData (elems);
}

atau nyatakan prefiks untuk dimuat (requirejs):

declare module "i18n!*" {
    //const m: { [key: string]: string };
    const m;
    export = m;
}

Kemudian di suatu tempat di sumber lib itu menggunakannya:

const oldCleanData = $.cleanData;
$.cleanData = function (elems: JQuery) {
..
    oldCleanData(elems);
};

Ketika modul seperti itu (dari lib) akan diimpor di suatu tempat di main, itu akan gagal dikompilasi.

Dalam sumber lib Anda, Anda harus menggunakan direktif /// <reference types="" /> (atau /// <reference path="" /> ) untuk memastikan bahwa pengetikan yang diperlukan ada setiap kali perpustakaan Anda diimpor. Dengan cara itu tidak harus di "sertakan"; ketika diimpor, tipe yang direferensikan secara otomatis akan ditambahkan ke proyek.

@ andy-ms terima kasih, saya telah merefaktor lib saya dan sekarang sebuah proyek dimana npm-link-ed sedang dikompilasi dengan baik.

Tidak yakin apakah ini reproduksi yang terlalu besar tetapi saya mendapatkan hal yang sama dari instalasi barebone CLI dengan angular @ next dan typescript @ next yang dilakukan dengan Observable<T> !== Observable<T> :

https://github.com/intellix/angular-cli-red
https://github.com/intellix/angular-cli-blue

Biru mengimpor dan menggunakan komponen dan layanan dari Merah

@intellix Bisakah Anda mendapatkan contoh bahwa kesalahan hanya menggunakan baris perintah tsc ? Sulit untuk mengetahui versi skrip ng yang digunakan.

@ andy-ms Saya masih mengalami masalah ini. Ini terjadi pada saya ketika mencoba menggunakan tautan npm antara ekstensi vscode saya buat. Mereka semua mengimpor vscode yang menyebabkan kesalahan pengenal duplikat.
TS Version 2.7.0-dev.20171118

Bagi saya itu berhasil memetakan misalnya "rxjs / *" ke folder rxjs tertentu dalam node_modules di bagian jalur file tsconfig.
Sekarang semuanya berfungsi dengan baik dengan tautan npm.

Saya juga telah melihat ini terjadi ketika beralih dari symlinked ke non-symlink dari link update versi ke sebuah paket.

Lihat pertanyaan SO ini juga: https://stackoverflow.com/questions/38168581/observablet-is-not-a-class-derived-from-observablet

@dakaraphi @JoshuaKGoldberg Dapatkah Anda memberikan petunjuk untuk mereproduksi skenario ini?

Dengan perilaku baru kita tidak boleh menyertakan paket jika kita telah melihat paket lain dengan nilai "versi" yang sama di package.json . Jika Anda memiliki banyak instalasi dengan versi berbeda, Anda akan mendapatkan dua salinan modul yang berbeda. Itu mungkin menjelaskan mengapa pembaruan versi akan merusak ini, jika itu hanya mempengaruhi satu dari dua instalasi.

@ andy-ms Contoh yang saya miliki adalah repositori berikut:

  1. https://github.com/dakaraphi/vscode-extension-fold
  2. https://github.com/dakaraphi/vscode-extension-common

Saya menggunakan instalasi npm lokal untuk mereferensikan vscode-extension-common dari vscode-extension-fold

Jika Anda melakukan checkout repositori ini, mereka saat ini berfungsi karena saya memiliki solusi pemetaan jalur di package.json dari vscode-extension-fold . Namun, jika saya memahaminya dengan benar, saya tidak memerlukan solusi tersebut.

@dakaraphi Terima kasih! Sepertinya kesalahan ini disebabkan vscode.d.ts ditulis sebagai deklarasi ambient global dan bukan sebagai modul eksternal. Saya telah membuat Microsoft / vscode-extension-vscode # 90.

Ini masih tidak berhasil untuk saya ketika saya mencoba menautkan 2 paket, masing-masing memiliki ketergantungan pada rxjs . Saya menggunakan [email protected] dan [email protected] . Kedua paket tersebut menggunakan versi yang sama persis. Apakah ada yang punya solusi untuk ini?

@SamVerschueren Bisakah Anda memberikan instruksi khusus untuk mereproduksi kesalahan? Juga uji dengan typescript@next .

@ andy-ms Saya akan melihat apa yang dapat saya lakukan!

@ andy-ms Berikut repositori reproduksi kecil https://github.com/SamVerschueren/ts-link-6496. Saya menggunakan [email protected] untuk mereproduksi ini.

  1. Instal kedua dependensi untuk mod-a dan mod-b
  2. Kompilasi mod-b dengan yarn build
  3. Kompilasi mod-a dengan yarn build

Langkah 3 akan gagal dengan kesalahan berikut

src/index.ts(7,15): error TS2345: Argument of type 'UnaryFunction<Observable<string>, Observable<string>>' is not assignable to parameter of type 'UnaryFunction<Observable<string>, Observable<string>>'.
  Types of parameters 'source' and 'source' are incompatible.
    Type 'Observable<string>' is not assignable to type 'Observable<string>'. Two different types with this name exist, but they are unrelated.
      Property 'buffer' is missing in type 'Observable<string>'.
src/index.ts(7,47): error TS7006: Parameter 'result' implicitly has an 'any' type.

Masih mengalami masalah ini dengan [email protected]. Juga mencoba ketikan @ next dan memiliki masalah yang sama.

Akar masalah tampaknya adalah bahwa paket tertaut masih merujuk definisi tipe di lokal mereka sendiri node_modules daripada menggunakan pengetikan dari node_modules tempat mereka terhubung, bila memungkinkan. Itu dikombinasikan dengan fakta bahwa:

  1. global tidak dapat didefinisikan ulang

    • ini menyebabkan kompilator mengeluh ketika global didefinisikan baik dalam proyek induk node_modules serta node_modules dalam paket terkait

  2. kelas yang identik tidak dapat ditugaskan satu sama lain

    • ini menyebabkan kompilator mengeluh ketika mencoba untuk menetapkan variabel yang tipenya adalah kelas dari proyek induk node_modules ke nilai yang dikembalikan oleh paket tertaut yang tipenya ditentukan dalam node_modules

Saya telah dapat mengatasi masalah ini menggunakan variabel config paths . Untuk modul yang definisinya berasal dari @types/* , seperti yang disarankan di sini , Anda cukup menggunakan:

"paths": {
  "*": ["node_modules/@types/*", "*"]
}

Jika Anda mengalami masalah ini dengan paket yang dibundel dengan definisi tipe yang menentukan kelas atau global, Anda harus menambahkannya secara manual. Misalnya, rxjs :

"paths": {
  "rxjs": ["node_modules/rxjs"],
  "rxjs/*": ["node_modules/rxjs/*"]
}

Saya juga mengalami masalah dengan symlink ketika saya menambahkan paket lokal, menggunakan TS 2.8.3:

},
"devDependencies": {
    "@types/MyLib": "file:../MyLib/bin/npm/@types"
},

Sejak v3, npm rupanya menginstal ini dengan symlink daripada menyalin file.

Namun, ketika saya mencoba mengompilasi, kompilator melihat file definisi tertaut sebagai dua file terpisah dan saling bertentangan:

node_modules\@types\MyLib\index.d.ts(3,11): error TS2300: Duplicate identifier 'Foo'.
C:/MySolution/MyLib/bin/npm/@types/index.d.ts(3,11): error TS2300: Duplicate identifier 'Foo'.

Jika saya menyalin file secara manual, itu berfungsi seperti yang diharapkan. Saya dapat menyiasatinya dengan menyetel typeRoots: ["./node_modules/**/"]

Apakah halaman ini membantu?
0 / 5 - 0 peringkat