Typescript: تعريفات نوع مكررة مع ارتباط npm

تم إنشاؤها على ١٥ يناير ٢٠١٦  ·  147تعليقات  ·  مصدر: microsoft/TypeScript

باستخدام TypeScript 1.7.3.

افترض أن لدي حزم npm أدناه.
يتم إنشاء ملفات التصريح بواسطة مترجم TypeScript ، ويُشار إليها من الحزم الأخرى عن طريق الطريقة الموضحة هنا .

الحزمة أ

ts src:

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

إعلان ts:

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

الحزمة- ب (يعتمد على الحزمة- أ):

ts src:

import ClassA from 'package-a';

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

إعلان ts:

import ClassA from 'package-a';

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

package-c (يعتمد على الحزمة أ والحزمة ب):

ts src:

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

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

السطر الأخير يتسبب في حدوث خطأ أثناء التجميع:

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

عندما أقوم بإزالة السطر private foo; من إعلان package-a ، لا يصدر TypeScript أي خطأ.
لكن هذا الحل مؤلم بعض الشيء.

أدرك أن عرض الخصائص الخاصة للإعلان يتم حسب التصميم (https://github.com/Microsoft/TypeScript/issues/1532).
أعتقد أن TypeScript يجب أن يتجاهل الخصائص الخاصة عند تجميع المهام المتغيرة.
أم أن هناك أي حل أفضل لهذا؟

@types Bug Fixed

التعليق الأكثر فائدة

لقد دمجت للتو تغييرًا سيحاول اكتشاف الحزم المكررة بناءً على اسمها وإصدارها ، واستخدام واحدة فقط. يرجى تجربته باستخدام typescript@next عندما يتم نشر ذلك لاحقًا.

ال 147 كومينتر

لا يوجد سوى إعلان جذر واحد ClassA هنا ، لذلك يجب ألا يحدث هذا الخطأ.

حسنًا ، آسف لأنني وجدت أن هذا متعلق بـ npm link .

عندما أستخدم npm link ، يتم تثبيت الحزم على النحو التالي ، لأنها ببساطة تخلق روابط رمزية.

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

كما هو موضح ، يبدو أن هناك ملفين مختلفين للإعلان عن package-a.
إذا قمت بتثبيت الحزم عادةً باستخدام npm install ، فلن يحدث هذا لأن الإعلان عن package-a غير مدرج في package-b في هذه الحالة.

آمل أن يكون هناك حل لهذا على أي حال ، لكنه قد يكون صعبًا وذو أولوية منخفضة.

انتهى بي الأمر بعدم استخدام npm link ، ولم يعد هذا الأمر مهمًا بالنسبة لي.

عادل بما فيه الكفاية ، ولكن شخص آخر قد:

يوجد بالفعل ملفان على القرص مع إعلانين عن ClassA. لذا فإن الخطأ هو الصحيح. لكننا نحتاج إلى النظر في وحدات العقد عندما نقارن هذه الأنواع. تم الإبلاغ عن هذه المشكلة من قبل في https://github.com/Microsoft/TypeScript/issues/4800 ، بالنسبة إلى Enums ، قمنا بتغيير القاعدة إلى فحص شبه اسمي. ربما تفعل الشيء نفسه للفصول.

+1 على هذا مع TS 1.7.5 مع جميع الحزم ذات الصلة المرتبطة بـ NPM. حاولت إنشاء حقيبة تجريبية تعرض المشكلة ولكن لم أستطع. بغض النظر عما جربته ، كان TS مناسبًا للسيناريو الذي أراه فشل مع TS2345 في طلبي ، وبقدر ما أستطيع أن أقول ، كانت جميع نسخ ملف d.ts المشكل روابط رمزية إلى نفس الملف ، لذلك لا ينبغي أن يكون هناك تم اختلاف الإعلانات داخل النوع. سيكون من الجيد أن يشير الخطأ المنبعث من Typescript إلى الملفات التي أعلنت عن النوعين غير المتوافقين ، حيث قد يلقي ذلك الضوء على شيء لا أفكر فيه. في الوقت الحالي ، يشير إلى وجود تعريفين ولكنه لا يفعل شيئًا لمساعدة المطور في تحديد المشكلة.

كحل بديل ، يمكنك استخدام <any> في التعبير المتعارض لتخطي فحص النوع. من الواضح أن هذا قد يتطلب منك عمل نوع آخر من التعليقات التوضيحية حيث ربما لم تضطر إلى ذلك من قبل. آمل أن يتمكن شخص ما من عزل هذه المشكلة في مرحلة ما.

تحرير: أوضح أن رابط NPM يعمل في حالتي

تم ملاحظة توفر TS 1.8 ، وتم ترقيته ولا تزال المشكلة موجودة في هذا الإصدار أيضًا.

نشكرك على كل العمل في تحليل وتوثيق هذه المشكلة. نواجه نفس المشكلة في بعض قواعد التعليمات البرمجية الخاصة بنا. قمنا بنقل بعض المشاريع لاستخدام التبعيات package.json بشكل صحيح ولكننا نشاهد هذا الآن عند استخدام npm link أثناء التطوير.

هل هناك أي شيء يمكنني المساعدة في حل هذه المشكلة؟

أنا أستخدم Lerna الذي يربط الحزم حولها وأرى المشكلة هناك أيضًا. نسخة مطبوعة 2.0.3.

لسوء الحظ ، تعد Lerna وروابطها الرمزية مطلبًا صعبًا ، لذلك استخدمت هذا الحل السيئ لتجميع هذا بشكل جيد مع الاستمرار في التحقق من الكتابة بشكل صحيح من قبل المستهلكين:

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

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

الفصل صغير جدًا ، لذا لم يكن ذلك شاقًا ، ولا أتوقع أن يتغير أبدًا ، ولهذا السبب أعتبر هذا حلًا مقبولًا.

لمعلوماتك ، لقد انتهيت هنا أيضًا كنتيجة لاستخدام npm link والحصول على هذا الخطأ. هل وجد أي شخص حلاً لهذا؟

xogeny ، هل يمكنك توضيح كيفية تسبب رابط npm في حدوث هذه المشكلة لك؟

mhegazy حسنًا ، لقد بدأت في الحصول على هذه الأخطاء مثل الخطأ أعلاه (باستثناء أنني كنت أستخدم Observable من rxjs ، على سبيل المثال ، "النوع" ملحوظ "غير قابل للتخصيص لكتابة" ملحوظ "). هذا ، بالطبع ، بدت غريبة لأن الاثنين كنت أشير إلى Observable من نفس الإصدار بالضبط من rxjs في كلتا الوحدتين. ولكن حيث "التقى" النوعان ، تلقيت خطأ. وجدت أخيرًا هذه المشكلة حيث أشار @ kimamula إلى أنه إذا استخدمت npm link ، فسوف تحصل على هذا الخطأ. لقد عملت ، مثل الآخرين ، على حل هذه المشكلة (في حالتي ، قمت بإنشاء واجهة مكررة للوظيفة I فقط مطلوب في وحدة واحدة ، بدلاً من الإشارة إلى rxjs ).

هل هذا الجواب على سؤالك؟ أسأل لأنني لا أعتقد أن حالتي تبدو مختلفة عن الحالات الأخرى هنا ، لذا لست متأكدًا مما إذا كان هذا يساعدك.

لقد قمنا بعمل في TS2.0 خصيصًا لتمكين سيناريوهات npm link (راجع https://github.com/Microsoft/TypeScript/pull/8486 و # 8346). هل لديك نموذج يمكنني من خلاله إلقاء نظرة على المكان الذي لا يزال فيه رابط npm لا يعمل من أجلك؟

هاه. أنا أقوم بتشغيل 2.0.3 (راجعت). سأحاول إنشاء حالة قابلة للتكرار.

بالمناسبة ، يجب عليك متابعة سلاسل الرسائل هذه لأنها تشير إلى أن هذه لا تزال مشكلة اعتبارًا من TS 2.0:

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

المشكلة التي أراها في Lerna repo متضمنة إلى حد ما ، لذلك قمت بعمل نسخة مجردة منها على https://github.com/seansfkelley/typescript-lerna-webpack-sadness. قد يكون خطأ webpack / ts-loader ، لذلك قمت بتقديم https://github.com/TypeStrong/ts-loader/issues/324 هناك أيضًا.

أنا أستخدم الإصدار 2.0.3 من الكتابة المطبوعة وأرى هذا الخطأ في Observable كما هو موضح أعلاه ، على سبيل المثال

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>'.

أنا أضرب هذا في حزمة Lerna monorepo أيضًا. يبدو أن معظم أجزاء نظام الكتابة ، وليس كلها ، تستخدم المسار الحقيقي للتعرف على الملفات بشكل فريد. إذا سافرت إلى أسفل الفرع الذي يستخدم مسار الارتباط الرمزي بدلاً من المسار الحقيقي ، فسوف ينتهي بك الأمر بأنواع متطابقة ولكن مختلفة.

هذه مشكلة وحشية جدًا ستؤثر فقط على قواعد أكواد أكثر تعقيدًا ، ويبدو أنه من المستحيل حلها دون اتخاذ إجراءات صارمة ، لذلك آمل أن أقنعكم جميعًا بإعطائها الاهتمام الذي تستحقه. 😄

يكون ذلك أكثر وضوحًا في الحالات التي يكون لديك فيها تطبيق يعتمد على Dependency A ، وتعتمد Dependency A على Dependency B وتبيع كائنات تحتوي على أنواع من Dependency B. التطبيق والاعتماد A كلاهما npm link Dependency B ونتوقع أن يكون قادر على استيراد أنواع منه وجعلهم يصفون نفس الشيء.

ينتج عن هذا رسائل خطأ عميقة ، وأنا على وشك المرور وإلغاء جميع خصائص private و protected في مكتباتي لأنني فقدت الكثير من الوقت بالفعل لهذا :

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)

حقًا نقدر لكم جميعًا النظر في هذا ؛ شكرا لك!

tomdale هل تستخدم Webpack أو tsc أو أداة إنشاء أخرى؟ يبدو أن مشكلتي تحدث فقط عند تجميعها عبر Webpack (انظر الريبو المرتبط من تعليقي السابق ).

هذا صحيح ، إنه يستخدم ts-node (للتطبيق الجذر). ومع ذلك ، فإن التبعيات هي حزم مجمعة مع tsc .

لقد واجهت هذه المشكلة وهي مشكلة كبيرة بالنسبة لنا لأننا نحاول تقسيم نهايتنا الخلفية إلى العديد من المكتبات الصغيرة. أثناء التطوير ، نحتاج غالبًا إلى ربط المستودعات الخاصة بنا في npm. المشكلة المحددة التي واجهتها والتي دفعتني إلى العثور على هذا هو استخدام المرصدات والواجهات rxjs:


// 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({});
    }
}

يعمل هذا إذا لم أكن npm link ، لكن عندما أفعل ، أحصل على:

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>'.

الاقتراح الوحيد الذي يمكنني تقديمه هو تجنب private . لم أعد أنشر أي حزم تحتوي على private بعد الآن بسبب هذه المشكلة واستخدم فقط بادئات على غرار JavaScript _ بدلاً من ذلك. لقد واجهت ذلك مع https://github.com/Microsoft/TypeScript/issues/7755 وهو نقاش مشابه حول سبب دخول private إلى نظام من النوع الاسمي بدلاً من النظام الهيكلي ، ومن ثم حظره على مشاريع خاصة لأنه من السهل جدًا أن ينتهي الأمر باختلافات في الإصدارات (على سبيل المثال NPM 2 أو استخدام npm link ).

blakeembrey عندما تقول تجنب الخصوصية ، هل تقترح أنه يمكنني تغيير شيء ما في الكود الخاص بي؟ أفترض أن تعريف النوع القابل للملاحظة هو المشكلة ، أليس كذلك؟

jeffwhelpley نعم ، آسف ، أنت لست على خطأ. إنه Observable . لسوء الحظ ، فإن نصيحة تجنب private ضئيلة جدًا ولم تكن قابلة للتطبيق تمامًا عليك 😄 ربما يمكنك إصدار مشكلة ، كما أفترض ، rxjs حول استخدام private في واجهاتهم العامة؟

تحرير: لقد علقت في الغالب لأنني تابعت المشكلة في وقت سابق وتجنب الانضمام إلى تجربتي الخاصة ، لكنني اعتقدت أنه يمكنني تدوين أفكاري مرة أخرى أيضًا بدلاً من ذلك فهي تشبه https://github.com/Microsoft/TypeScript/issues/ 6496 # issuecomment -255232592 (حيث يقترح tomdale إزالة private و protected ، لقد فعلت الشيء نفسه منذ فترة).

حصلت على انطباع من mhegazy أنه شعر بعدم وجود مشكلة مع npm link . ولكن لا يزال يبدو أنه يعاني منا والآخرين. إذن لست متأكدا أين تقف هذه القضية؟ هل هي مشكلة معترف بها في TS 2.0+ أم أنني أفتقد حلًا بديلًا في مكان ما؟!؟

أواجه هذه المشكلة نفسها ولا يبدو أن سببها هو npm link . ما زلت أحصل عليه إذا قمت بتثبيته باستخدام npm install file.tar.gz . ها هو الخطأ:

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>'.

هذا ما يبدو عليه 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);
  }

إنها تشتكي من خط this.user$ . Stormpath تعريف user$ على النحو التالي:

@Injectable()
export class Stormpath {

  user$: Observable<Account | boolean>;

xogeny Odd ، ما فهمته هو أن هوية التعريف مرتبطة بموقع الملف مما يعني أنها ستتسبب دائمًا في حدوث مشكلات باستخدام npm link (لأن التبعية npm link ed ستكون لها تبعيات خاصة بها) . ربما تم تغيير هوية التعريف - قد يكون استخدام تجزئات الملفات حلاً جيدًا في TypeScript. لسوء الحظ ، هناك فقط اثنتي عشرة طريقة مختلفة للوصول إلى وحدات مكررة في JavaScript ( npm install من GitHub ، npm install ، النسخ اليدوية ، يمكن أن تؤدي تعارضات الإصدار إلى هبوط الإصدار نفسه في مواقع مختلفة بسبب كيف تعمل خوارزمية دقة وحدة العقدة ، إلخ).

تضمين التغريدة ولكن بعد ذلك عن ماذا كان هذا ؟

ملاحظة ، أنا لا أشكو. أحاول فقط معرفة ما إذا كان هناك بعض الأمل في حل هذه المشكلة أم لا. إنها شوكة خطيرة في جانبنا لجميع الأسباب التي ذكرها jeffwhelpley .

xogeny أعلم ، أنا أحاول أيضًا ، أود أن أراها تم حلها بشكل صحيح 😄 لقد قرأت المشكلات المرتبطة ، لكنها كلها مصممة لحل المسار الحقيقي للرابط الرمزي الذي يعني ما إذا كان لديك ملفان (حقيقيان) سيظلون متعارضين لأنهم سيحلون مواقع مختلفة. وهذا ما يحدث عندما تقوم بـ npm link من مشروع إلى آخر لأن كلاهما سيكون لهما تبعيات خاصة به يمكن أن تختلف مع الرموز المعاد تصديرها من حزمة npm link ed.

تحرير: يمكنني أن أؤكد ، كل المشاكل بسبب ملفين. سيؤدي npm link إلى تشغيله لأنه من السهل أن يكون لديك تبعية في الريبو الذي قمت بربطه للتو وهو نفس التبعية كما في المشروع الذي قمت بالربط به. قد يكون إعادة الشراء البسيط هو إجراء npm install لنفس التبعية على مستويين مختلفين من التطبيق ومراقبتهما بالخطأ.

image

لأي شخص يتابع هذا الموضوع ... جربت الحل البديل الموضح هنا ويبدو أنه يعمل (حتى الآن).

لقد استنكرت هذا الخطأ.

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

نظرًا لوجود عمليتي تثبيت rxjs ، نحصل على:

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>'.

لدي حل بديل يعمل بشكل رائع مع سطر الأوامر ، ولكن لا يزال الاستوديو المرئي معطلاً تمامًا: https://github.com/Microsoft/TypeScript/issues/11107#issuecomment -254003380

الحل الجديد الخاص بي لـ Windows + Visual Studio 2015 هو نسخ مجلد xlib Library src و dist إلى مجلدات node_modules\xlib\src و node_modules\xlib\dist من المشروع المستهلك.

هنا هو الجزء المهم من البرنامج النصي للملفات الدفعية robocopy إذا أراد أي شخص ذلك:

: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

نأسف للخطأ مرة أخرى في هذه المشكلة ، ولكنه يمثل عبئًا خطيرًا على مشروعنا لعدم قدرتنا على تنفيذ npm link أثناء إجراء التغييرات. أرغب في المساعدة في العلاقات العامة إذا كان بإمكان أحد المساهمين الحاليين في TypeScript إعطائي القليل من الإرشادات حول مكان بدء البحث في قاعدة التعليمات البرمجية.

أنا أيضًا أعاني من هذا. لقد اعتمدنا TS بدءًا من تطبيق صغير ، والآن قمنا بتقسيمه إلى وحدات فرعية وربطنا بينها و… BOOM. لن يتم تجميع TS بعد الآن. هل لا تزال هذه مشكلة في جميع علامات توزيع TS؟ أواجه هذا حاليًا في @rc (2.1.1).

heruan و jeffwhelpley هل يمكنك typescript@next ، لقد أصلحنا بعض المشكلات ذات الصلة. وإذا كنت لا تزال ترى المشكلة ، فيرجى تقديم مزيد من المعلومات حول إعداد مشروعك.

mhegazy أنا على Version 2.2.0-dev.20161129 وما زلت أواجه المشكلة. المشكلة المحددة هي أن لديّ مشروعًا واحدًا (دعنا نسميه ProjectA) يحتوي على "واجهة" (باستخدام فئة ، ولكن هذا حتى يمكنني استخدام الفصل كرمز لـ Angular 2 DI) على النحو التالي:

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

ثم في مشروع منفصل تمامًا (لنطلق عليه ProjectB) يحتوي على فئة تنفذ الواجهة من المشروع الأول مثل هذا:

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
}

عندما أفعل ترجمة مطبوعة عادية لـ ProjectB ، فإنها تعمل بشكل جيد. ولكن إذا قمت بتشغيل npm link ProjectA من الدليل الجذر لـ ProjectB ثم قمت بتشغيل tsc مرة أخرى ، فسأحصل على:

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>'.

لم أتمكن من التكرار في مشروع وهمي ، أعتقد أنني أفتقد سبب المشكلة ومن ثم لا يمكنني تكرارها. jeffwhelpley هل يمكنك نشر مشروع

heruan سأحاول إعداد ذلك.

واحد ، لمعلوماتك ، رغم ذلك. أعتقد أنني ربما وجدت حلًا. يتم حل المشكلة إذا كنت npm link rxjs في كل من ProjectA و ProjectB. هذا النوع من المنطقي لأنه في هذه الحالة ، يستخدم كل من ProjectA و ProjectB نفس ملفات rxjs بالضبط. بدون ذلك ، فهم يستخدمون ملفات مختلفة تقنيًا (على الرغم من نفس الإصدار):

إذا كان لديك npm link ProjectA من ProjectB ، إذن:

  • يشير ProjectB إلى node_modules / rxjs
  • يوجد مشروع أ كارتباط رمزي في node_modules / ProjectA و rxjs الذي يشير إليه موجود في node_modules / ProjectA / node_modules / rxjs

ولكن إذا كان لديك npm link rxjs في كليهما ، فسيتم ربط كلا المراجع rxjs هذه بنفس موقع npm العالمي بالضبط.

على أي حال ، من الواضح أن هذا لا يزال غير مثالي ، ولكنه على الأقل شيء يمكن أن يدفعنا إلى الأمام.

أيضًا ... لست متأكدًا مما إذا كان هذا مناسبًا أم مهمًا (سترى بمجرد أن أقوم بإعداد مشروع الاختبار) ، ولكن libs (مثل ProjectA و ProjectB) هما في الواقع مستودعات npm خاصة.

شكرًا لك jeffwhelpley على التلميح ، ولكن نظرًا لأنني أستخدم Lerna ، فإن جميع الوحدات مرتبطة بالفعل ببعضها البعض لذا فهم يقرؤون نفس الملف ، لكنني أعتقد أن مترجم TS يأخذ في الاعتبار مسار الارتباط وليس المسار الحقيقي. قد أكون مخطئًا ، لأنني لا أستطيع التكاثر في مشروع وهمي ، وأنا حقًا أخرج من الجنون ...

أي شخص هنا قادر على حل هذا بطريقة أنيقة؟

لاحظ أيضًا أن هذه ليست مجرد مشكلة في npm link ، ستواجه هذه المشكلة أيضًا في إصدارات الإنتاج ، عندما تشير التبعيات المشتركة إلى إصدار مختلف.

بمعنى آخر. يحتاج ProjectA إلى [email protected] ويستخدم ProjectB [email protected]

عند تثبيت ProjectA كعنصر تبعية في ProjectB ، سيكون لديك أيضًا أنواع مكررة ، حيث سيكون هناك على سبيل المثال إعلانان Observable ، واحد في node_modules/rxjs والآخر في node_modules/project_a/node_modules/rxjs

يمكنك التغلب على هذا من خلال السماح لإصدار rxjs في ProjectA بأن يكون شيئًا مثل ~4.9.0 ، بحيث لا يحتاج npm install إلى تنزيل نسخته الخاصة ، وسيستخدم بدلاً من ذلك إصدار ProjectB. لكن ضع في اعتبارك أن هذه ليست مجرد مشكلة تتعلق بسير عمل التطوير.

يتم النشر هنا وفقًا لاقتراح @ andy-ms. حاولت مرة أخرى أمس مع الإصدار 2.0.x الأحدث وما زلت تملكه.

أحصل على هذا من خلال كتابات Angular 1: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/10082#issuecomment -253023107

ركض في هذا مرة أخرى اليوم ، وتحديدًا مشكلة الروابط الرمزية. الإعداد الخاص بي هو شيء من هذا القبيل:

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

إذا كان لدي @types/angular ، فإن tsc يعمل بشكل جيد. إذا كان لدي المجموعة الكاملة ( @types/angular-{animate,cookies,mocks,resource,route,sanitize} ) ، فأنا أبدأ في تلقي الكثير من أخطاء النوع:

$ 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'.

لقد أصلحته بإضافة الأساس ../../node_modules/@types كـ typeRoots إلى tsconfig.json :

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

حاولت إضافة node_modules/@types المحلي ، لكن ذلك لم ينجح.

اختراقheruan الذي بدأت به هو تنفيذ برنامج npm الخاص بي للربط / إلغاء الربط بدلاً من استخدام وظيفة lerna. لذلك ، يمكنك القيام بشيء مثل lerna run link ثم في جميع ملفات package.json لديك نص برمجي npm يسمى link والذي يقوم بجميع روابط npm بما في ذلك (في حالتي) npm link rxjs . يبدو أنه يعمل بشكل جيد ، ليس بالتأكيد مثاليًا.

jeffwhelpley هل يمكنك مشاركة الحل الخاص بك هنا؟

yvoronen لا يمكنني مشاركة كل الكود الخاص بي ، لكن الحل الخاص بي موصوف أعلاه. على مستوى عالٍ ، المفتاح الذي وجدته هو التأكد من ربط npm ليس فقط بجميع المشاريع المحلية التي تعمل عليها ، ولكن أيضًا ربط npm libs الخارجية التي قد تسبب المشكلة (في حالتي ، rxjs هي المشكلة بسبب المتغيرات الخاصة في الكائن المرئي). لذلك ، أستخدم lerna لإدارة جميع lerna run link . تحت الكواليس ، يستدعي هذا npm run link داخل كل مجلد من مجلدات الجذر لمشروعي. لذلك ، يجب أن يكون لديك البرنامج النصي link المحدد في الحزمة الخاصة بك. json مثل هذا:

  "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"
  }

آمل أن يكون هذا منطقيًا ، ولكن يرجى إعلامي إذا كان لديك أي أسئلة.

كنت أرغب في تقديم تحديث. من تبادل مرتجل أجريته مع

  • أحد الحلول التي ندرسها هو مفهوم تمييز الحزم بناءً على إصدارها بالإضافة إلى اسم حلها. ليس لدي تفاصيل كاملة عما يمكن أن ينطوي عليه هذا الأمر.
  • والشيء الآخر هو توسيع المسار بالكامل للحصول على الهوية "الحقيقية" للرابط الرمزي. أعتقد أن هذا أبسط ، ولكنه محدود أكثر عندما يتعلق الأمر بالتعامل مع نفس الحزمة بإصدارات مختلفة ، ولكنه يساعد في حل عدد مناسب من الحالات.

هل أنت متأكد من أن تعليقك ينتمي إلى هذه القضية؟ يبدو تماما
مختلف.

في الخميس ، 12 كانون الثاني (يناير) 2017 ، الساعة 3:14 صباحًا كتب Nikos [email protected] :

ملاحظة ، أنا لا أستخدم أنواع أو رابط npm AFAIK.

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

-
أنت تتلقى هذا لأنك علقت.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment-272137732 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AAUAmcMXodOvU7coymMqGzTofD4pMagpks5rRgsogaJpZM4HFcWl
.

dobesv إنه في الواقع السبب الكامل وراء رؤية المشكلة في المقام الأول. يتعرف TypeScript على إعلان الفئة كإعلانين منفصلين لأنه لا يمكنه التمييز بين المسار المرتبط والمسار الحقيقي. الحل إما ل

  1. قم بتوسيع الارتباط الرمزي.
  2. تحقق لمعرفة ما إذا كانت العبوة التي تحتوي عليها هي نفسها.

DanielRosenwasser آسف تعليقي كان ردًا على تعليق شخص آخر "يوم الخميس ، 12 يناير 2017 ، 3:14 صباحًا كتب نيكوس @ . * >" ... من هذا وما قالوه لم أعد أتذكره ، أعتقد أنهم كانوا يسألون عن بعض المشاكل في سلسلة التعليقات هذه ، والتي لا علاقة لها بالرابط npm.

لكن أثناء وجودي هنا ، يجب أن أذكر أن هناك شيئًا مضحكًا حول الطريقة التي يلعب بها اسم الملف دورًا في الأنواع. واجهت اليوم مشكلة مع RxJS حيث اشتكت من أن طريقة كذا وكذا لم يتم تحديدها في Observable. والسبب هو أن مكتبة HTTP لديها نسختها الخاصة من rxjs والتي تختلف عن أي مكتبة أخرى. في الواقع ، وجدت أربع نسخ مختلفة من rxjs في شجرة node_modules الخاصة بي.

يبدو أن هذا نهج إشكالي سيستمر في كونه إشكاليًا ومربكًا.

إذا اختفى هذا المفهوم الكامل لاسم الملف بطريقة ما يلعب دورًا في هوية النوع ، أعتقد أن مشكلة ارتباط npm هذه ستختفي أيضًا.

ما زلت غامضًا بعض الشيء حول كيفية عمل ذلك ... أنا جديد على TypeScript. ولكن هذا نوع من الانطباع الذي لدي ، هو أن هذا الشيء "اسم الملف مهم" قد تسبب لي في بعض الارتباك فيما يتعلق بالمكتبات التي أستخدمها (ionic2 و angular2 و rxjs).

حسنًا ، المشكلة هي أن اسم الملف لا يزال هو هوية وحدة نمطية في جافا سكريبت ، لذلك لا يمكن أن يختفي تمامًا. هل يمكن لأي شخص التوسع في شرح المشكلات المتعلقة باستخدام المسار الأساسي (تحليل الارتباط الرمزي) فيما يتعلق بإصدارات الحزم المتعددة؟ إذا كانت هناك إصدارات متعددة من الحزم داخل شجرة ، فسيكون لها العديد من المسارات المطلقة الأساسية ، أليس كذلك؟

تحرير: لقد أدركت هذا بعد النشر ، وهذا التعليق يلخصه جيدًا:
https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -257016094

تم تجاهل exclude و compilerOptions.typeRoots تمامًا بواسطة tsc. لقد جربت كل التركيبات لتجاهل المسارات المرتبطة ، لكنها لن تفعل ذلك
إنها ترى الوحدة كمسار مختلف تمامًا ، مثل حل الارتباط الرمزي وعدم فهم الأنماط المستبعدة.

على سبيل المثال ، لدي G:\www\cim-service-locator npm مرتبط بـ npm link cim-service-locator . في مسار مشروعي في G:\www\cim-backend ، تظهر الأخطاء على النحو التالي:

crop

لقد جربت كل مجموعة ممكنة من الاستثناءات / التضمينات / أنواع الجذر ولكن لا يمكنني جعل tsc يتجاهلها. باستخدام 2.2-dev.20170131

لقد واجهنا هذه المشكلة باستخدام "npm link" (عبر مشكلة SPFx تم الإبلاغ عنها بواسطةwaldekmastykarz) وأيضًا بدون "رابط npm" (راجع الخطأ رقم 11436).

أدركت في النهاية أن صرامة مترجم TypeScript ناتجة عن حالات عدم التوافق التي يمكن أن تحدث بشكل واقعي بسبب التصميم الغريب لمجلد

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]

في هذا المثال ، يجب تثبيت B @ 2 في المجلدات الفرعية لتجنب التعارض مع تبعية A على B @ 1 . الآن ، افترض أن ClassB يمتد من ClassE ، ولدينا شيء مثل هذا:

ب / package.json

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

إذا طلبت حزمة C 's package.json [email protected] ، فيمكن أن تنتهي نسختان من ClassB غير متوافقين بالفعل. قد تفشل الشفرة في وقت التشغيل إذا حاولت استخدامها بالتبادل.

في هذا المثال ، يمنع TS2345 هذا الخطأ ، وهو أمر جيد. ومع ذلك ، فهو ليس ضروريًا: إذا تعامل المترجم مع نسختين من ClassB على أنهما مكافئتان ، فسيظل نظام النوع الخاص به متسقًا داخليًا وله سلوك حتمي.

هذا مهم لأن TS2345 ينتج في الغالب إنذارات خاطئة. تجبر هذه الإنذارات الكاذبة الناس على كتابة "مثل أي" أينما يشاركون الأنواع بين حزم NPM ، مما يتسبب في أخطاء أخرى. لذا فإن الصرامة تخلق مشاكل أكثر مما تحل.

أرغب في اقتراح الإصلاح التالي:

إذا كانت كل هذه الشروط صحيحة ، فلا تقم بالإبلاغ عن TS2345 للفصول ذات الأعضاء الخاصين:

  1. تتوافق التواقيع العامة وفقًا لطباعة بطة TypeScript المعتادة
  2. يتم تحديد الفئات في مجلدات حزمة NPM بنفس الاسم والإصدار (وفقًا لـ package.json)
  3. الفصول لها نفس المسار النسبي لوحدتها (على سبيل المثال "./lib/blah/Bdts")

إذا لم يتم استيفاء أي من هذه المعايير ، فلا بأس من الإبلاغ عن TS2345.

تضمين التغريدة

يتم تتبع خطأ seansfkelley Webpack بواسطة TypeStrong / ts-loader # 468

اهلا ياجماعة،
شخص ما وجد حلا ؟؟
لدي نفس المشكلة عندما أقوم بربط مشروع بآخر بـ RxJS.
شكر ؛)

مرحبًا ، الحل المؤقت هو التفاف الملاحظات التي تم إرجاعها بواسطة التبعية بـ Observable#from .

لا يوجد حل بعد. ؟

يبدو أن هناك مشكلتين هنا.

يبدو أن مستخدمي ts-loader الذين يتلقون أخطاء خاطئة للتعريفات المكررة ، ناتج عن إدخال غير صالح إلى API للمجمع. يتوفر إصلاح لذلك في TypeStrong / ts-loader # 468.

المشكلة الأخرى هي إذا كان لديك نفس الحزمة (نفس الحزمة npm + الإصدار) مثبتة مرتين محليًا على نظام الملفات (لا تستخدم npm link ) في مجلدين متداخلين ، إما مع Enums أو الفئات ذات الأعضاء الخاصين ، مقارنة ستفشل أنواع من هاتين الحزمتين باعتبارها غير متوافقة.
هذه المشكلة أكثر تعقيدًا وستتطلب عملاً إضافيًا من قبل المترجم "لإزالة تكرار" الحزم قبل معالجتها.

إذا لم تنطبق أي من هاتين الفئتين عليك ، فالرجاء تقديم مشكلة جديدة وتزويدنا بالمعلومات الكافية لإعادة إظهار المشكلة محليًا ، ويسعدنا إجراء المزيد من التحقيق.

الحل المعروف هو استخدام حل متعدد المشاريع من شأنه القضاء على المجلدات المكررة ، أي ضمان أن كلا المجلدين الفرعيين node_modules ينتهي بهما ارتباط رمزي لنفس الهدف.

يعد Rush (الذي نستخدمه) و Lerna أمثلة على ذلك.

smcatala يمكنك شرح الحل الخاص بك. أحتاج إلى إصلاحه بشكل عاجل. شكر.

امين
الوحدة النمطية "فو":

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

كود العميل في وحدة أخرى ، يعتمد على الوحدة النمطية 'foo':

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

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

@ leovo2708 الحل البسيط هو عدم استخدام npm link .

باستخدام ts 2.1 ، تمكنت من استخدام رابط npm مع مكتبة واحدة (دعنا نسميها xlib ، وهو مثالي الحقيقي) ولكنك ستحتاج إلى التأكد من أن الوحدات النمطية في مكتبتك ( xlib ) لا تتكرر الأحمال في مجلد node_modules للمشروع المستهلك.

أفعل هذا من خلال سير العمل التالي

  1. حذف node_modules
  2. npm link xlib الذي ينشئ رابط sym_link لـ xlib في مشروعي المستهلك node_modules
  3. npm install الذي يثبّت ما تبقى من تبعيات مشروع الاستهلاك الخاص بي

لم أكن أتابع هذه المحادثة حقًا أو أتحقق مما إذا كانت هذه المشكلة قد تغيرت / تم تعديلها منذ 2.2 ولكن فقط على الرغم من أنني أشارك الحل البديل الخاص بي لـ ts 2.1

في حال كان ذلك مفيدًا ، قمت بتجميع الحد الأدنى من إعادة صياغة التعريفات المتعددة لحالة التعداد هنا: https://github.com/rictic/repro-npm-link-typescript-issue

mhegazy نرى المشكلة أعلاه عند استخدام رابط npm ، على الرغم من أنني لا أعتقد أن هذا يؤثر على بقية تحليلك.

شكرًا جزيلاً ، أتمنى أن يتم إصلاحه قريبًا. ومع ذلك ، استخدمت حلاً جديدًا ، وهو تكرار أي ملفات باستخدام Observable. إنه ليس جيدًا ولكنه حل مؤقت فقط.

tsconfig.json تعيين المسار ، أضف تبعيات مكررة إلى paths ، لذلك سيتم تحميله من node_modules الصحيح بدلاً من المرتبط.

{
  "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"]
    }
  }
}

لست متأكدًا مما إذا كان مذكورًا هنا بالفعل ، ولكن هذا الحل نجح معي: https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001

إنه في الأساس نفس حل charpeni أعلاه ، باستثناء بدون البادئة "../" في المسارات. (وهو ما يبدو غريباً ، لأن هذا لا يعني أن ملف tsconfig.json سيكون في مجلد فرعي من جذر المشروع؟)

هذه فكرة رائعةcharpeni. لقد استخدمت إعداد المسارات هذا للتغلب على العديد من المشكلات المماثلة الأخرى ، ولكنه يبدو أيضًا مثاليًا لهذه المشكلة. في الواقع ، أتساءل عما إذا كان الإعداد الصحيح paths في المشروع المستهلك (وليس في كل مشروع مستهلك) قد يصرف انتباه مترجم TypeScript بعيدًا عن دقة العقدة التالية. إذا نجح ذلك ، فسيكون اختراق O (1) بدلاً من اختراق O (n). في الأساس مثل هذا المخطط من شأنه تشغيل دقة العقدة بشكل ثابت ، ثم حشو النتائج في tsconfig.

أقوم بتجربة هذه الأشياء بشكل شبه علني إذا أراد أي شخص المشاهدة (أو المساعدة ...). ربما سأحاول الفكرة أعلاه بعد ذلك.

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

لتسهيل الاستخدام ، يمكنك أيضًا تعيين المسارات على النحو التالي:

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

يعد ارتباط npm جزءًا مهمًا من سير العمل عند العمل مع حزم متعددة بدلاً من بنية أحادية الريبو. يجب أن يكون TS قادرًا على رؤية أن الحزمتين متطابقتان وليست خطأ

charpeni لم أستطع الحصول على الحل البديل. فقط لأكون واضحًا ، إلى أي tsconfig.json يجب إضافة هذا؟ الحزمة الجذرية أم الحزمة المرتبطة؟

أواجه هذه المشكلة أيضًا. بدأ الأمر فجأة يوم الاثنين ، ولست متأكدًا من السبب. هذا يعيق التنمية حقًا خاصة عندما يتعلق الأمر بتطوير حزم لمشاريعنا. لقد جربت العديد من الحلول لإصلاح هذا. لا يزال تشغيل mklink /j في Windows يتسبب في حدوث هذه المشكلة ، لذا فهي ليست مشكلة ارتباط npm. إذا كان لدى أي شخص حل بديل أو إصلاح ، فسيكون هذا مساعدة كبيرة.

الحل البديل الخاص بي هو ربط npm بكل حزمة "مكررة" في كل من الحزمة الجذر والتبعية ، لأنهما يشيران إلى نفس الملفات مرة أخرى.

راجع للشغل ، هذه المشكلة لا علاقة لها بـ @types

انتهى بنا الأمر باستخدام نمط الكرة الأرضية.

felixfbecker للتنفيذ ، يتوفر هنا: https://github.com/sherweb/ng2-materialize/blob/master/demo-app/tsconfig.json#L19 -L22

لدي مشكلة مماثلة فيما عدا أنها مرتبطة تمامًا بـ @ type / node.

تعتمد libA على @ العقدة / الأنواع
يعتمد libB على أنواع libA و @ node /
يعتمد libC على أنواع libA و libB و @

libA يبني بشكل جيد.
libB npm المرتبط بملف libA builds.
libC npm المرتبط بـ libA و libB يفشل في فحص الكتابة بأخطاء مثل

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'.

حاولت العبث مع "الأنواع" و "typeRoots" دون حظ.

charpeni يبدو أن مشروعك يعتمد أيضًا على @

nicksnyder التي قد تكون بسبب أنها إصدارات مختلفة ، و @types/node هو تصريح عام ، مما يعني أنه لا يمكنك تحديد نفس الأسماء مرتين. هذا هو السبب في أنه من الأفضل أن لا تعتمد الحزم على الأنواع البيئية ، يجب أن يوفرها المستخدم:
https://github.com/Microsoft/types-publisher/issues/107

nicksnyder واجهت مشكلة مماثلة وتمكنت من حلها عن طريق ربط جميع المشاريع الثلاثة بتثبيت @ type / node واحد. نظرًا لأن التعريفات يتم تعريفها في نفس الملف لم تعد مكررة

felixfbecker لقد

FWIW libA هو https://github.com/Microsoft/vscode-languageserver-node/tree/master/jsonrpc ، libB هو https://github.com/Microsoft/vscode-languageserver-node/tree/master/client and libC هو امتداد كود VS الخاص بي.

uncleramsay كيف بالضبط فعلت npm link @types/node ؟

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

أود أن أقوم بحل الربط ، لكنني قمت أيضًا باختراق هذا الأمر عن طريق حذف تبعية @ type / node في libA و libB ، وإضافة refs.d.ts التي تحتوي على مراجع محلية لنسخة libC من العقدة.

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

لقد اكتشفت أنني كنت قادرًا على حل المشكلات التي كنت أواجهها من الوصف الوارد في التعليق في https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -225303098

أضفنا فقط دعمًا لتحليل الارتباط الرمزي للوحدات النمطية ...

في أماكن منفصلة في قاعدة الشفرة عندما كنا نستخدم نمطين مختلفين للمراجع:

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

هذين غير متوافقين في الحالة التي تكون فيها node_modules مرتبطة بشكل رمزي ، حيث يتم توسيع دقة الوحدة النمطية (مع types= ) إلى المسار الحقيقي ، ولكن path= ليس كذلك. ينتج عن هذا ملفين مختلفين يشار إليهما عند التحويل البرمجي باستخدام tsc --listFiles ، الارتباط الرمزي والمسار الحقيقي.

كان الحل الذي ذهبنا إليه هو استخدام أحدهما أو الآخر ، ولكن ليس كليهما مطلقًا. كما ساعد في تحديد typeRoots: [] في tsconfig لتجنب تحميل المترجم تلقائيًا الأنواع من node_modules/@types في حالة استخدام النمط reference path= .

أعتقد أن التفضيل للمضي قدمًا (على الأقل بالنسبة لنا) هو تفضيل النمط types= .

من الناحية المثالية ، يفضل التوسع إلى المسار الحقيقي في reference path= ، والتحقق من المسارات المطابقة المكررة لتجنب مثل هذه المشكلات.

أتمنى أن يساعد هذا شخص ما.

nicksnyder ، يجب أن تكون قادرًا على القيام بشيء مثل هذا:

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

بهذه الطريقة ، يشير B & C إلى نفس الملفات الموجودة في A بالضبط.

uncleramsay يجب أن تدرك أنهم جميعًا نفس الإصدارات ، والتي ربما لم تكن موجودة من قبل

ألا يمكن أن تكون تبعيات الأقران حلاً لهذا؟
http://codetunnel.io/you-can-finally-npm-link-packages-that-contain-peer-dependencies/

تم اختراع تبعيات الأقران لموقف يريد فيه المكون الإضافي أن يقول ما يتوافق معه. إنهم يعملون بشكل جيد في هذه الحالة. لكنها تسبب الكثير من المشاكل إذا بدأ الناس في تحويل كل تبعياتهم إلى تبعيات نظير ، على أمل تجنب تكرار "تثبيت npm".

لقد أمضينا شهورًا في طردهم من مستودعاتنا الداخلية. عند استخدامها كما أعتقد أنك تقترح ، تسمح لك تبعيات الأقران بحل مشكلة إصدار جنبًا إلى جنب عن طريق استبدالها بالعديد من المشكلات الجديدة:

  • تم قلب الشجرة بأكملها ، أي أن كل حزمة تصبح الآن مسؤولة عن الاعتماد الشديد على الحزم التي كانت تبعيات غير مباشرة ، في كثير من الحالات دون أي فكرة عن الغرض من

  • إذا تمت إزالة تبعية الأقران ، فمن المحتمل ألا تتم إزالة هذه التبعيات الصعبة أبدًا

  • يميل مؤلفو الحزم إلى استخدام نطاقات واسعة لأنماط إصدارات أقرانهم ، زاعمين أنهم يعملون مع إصدارات لم يختبروها بالفعل ؛ البنيات المكسورة تصبح فجأة مشكلة المستهلك

احسنت القول.

الحلول

فيما يلي 3 خيارات للحلول التي استخدمتها:

الخيار 1: استخدام vscode وليس visual studio

المترجم tsc أكثر تسامحًا من VS2017 ، ربما لأن VS2017 يزحف إلى الكود (بما في ذلك node_modules ) لتوفير تحسس لطيف وبالتالي يتم الخلط. ومع ذلك ، لدي مشروعات كبيرة معقدة متعددة الوحدات npm ، لذا استخدم VS2017 ... لذا اقرأ الخيارين 2 و 3 إذا كانت لديك احتياجات مماثلة ...

الخيار 2: انبعث d.ts

إذا كنت تستخدم outDir و rootDir (في tsconfig.json ) ، يجب أن تصدر الوحدة lib ذات الارتباط الرمزي إعلانات d.ts ويجب أن تكون هذه الإقرارات في وحدة lib-module خاصية package.json types .

فيما يلي مثال على الشكل الذي يجب أن يبدو عليه tsconfig.json لوحدة lib الخاصة بك

{
  "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"
  ]
}

ويجب أن يتضمن package.json للوحدة lib الخاصة بك شيئًا مثل ما يلي:

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

يعمل هذا الخيار بشكل جيد ، والمشكلة الرئيسية هي أنه في الاستوديو المرئي عند تصحيح الأخطاء أو "الانتقال إلى التعريف" أو "إظهار كافة المراجع" ، فإنه سيظهر لك d.ts وليس ملفات المصدر المطبعية الفعلية ، والتي تتغلب على الفائدة الرئيسية من الاستوديو المرئي (التنقل في المشاريع الكبيرة)

إذا كنت تريد رؤية مثال فعلي لهذا في البرية ، فابحث عن وحدة npm xlib v8.5.x

الخيار 3: انبعث .js مع المصدر (خياري المفضل)

يمكنك استخدام ملفات .ts مباشرة للكتابة في وحدات lib ذات الروابط الرمزية! ولكن فقط إذا كنت لا تستخدم ملف outDir`` and rootDir in your tsconfig.json ```. سيتيح ذلك لمراجع VS2017 العمل بشكل صحيح. فيما يلي إعدادات التكوين التي تحتاجها:

{
  "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"
  ]
}

ويجب تغيير package.json للوحدة lib إلى:

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

التحذيرات (الأشياء التي لن تعمل مع الخيار 3)

الحلول المذكورة أعلاه العمل إلا إذا كان كل ليب وحدة لا تنبعث منها نوع المعلومات الزائدة عن الحاجة. على سبيل المثال ، اعتدت على جعل مكتبتي xlib تعرض تعريفات النوع @types/async . ولكن بعد ذلك كان لدي مكتبة أخرى أشارت أيضًا بشكل مستقل إلى @types/async . يؤدي استخدام ملفات .ts مباشرة للكتابة إلى قيام tsc باستيراد async من وحدتين lib ، مما يؤدي إلى عرض أشكال مختلفة من مشكلات duplicate identifier . لحل هذه المشكلة ، يلزمك إما عدم استيراد نفس @types من وحدات lib-modules متعددة ، أو استخدام الخيار 2 .d.ts الحل البديل

ملخص

آمل أن يوفر لك هذا الساعات التي استغرقتها .... بشكل عام هذا مؤلم للغاية ، وآمل أن يتمكن فريق الطباعة على الطباعة من إصلاح الوحدات ذات الروابط. لكنها على الأقل تعمل الآن (قبل 2.x كان من المستحيل أساسًا)

الحل البديل الذي نشره mhegazy في https://github.com/Microsoft/TypeScript/issues/11916#issuecomment -257130001 (نوع من الحل البديل 2jasonswearingen) حل هذا الأمر بالنسبة لنا عند استخدام الوحدات المرتبطة في مشروع lerna!

لقد اعتقدت فقط أنني سأشارك تجربتي ... محاولة إنشاء / استخراج lib من مشروع موجود بحيث يمكن مشاركة lib عبر مشاريع أخرى.

نظام التشغيل Windows 10 Enterprise
VS 2015 Update 3
أدوات لـ VS2015 2.2.2
كود VS 1.12.2
الطباعة المطبوعة 2.2.2
NPM: 3.10.9
العقدة: 6.9.2

لدينا مشروع VS 2015 ASP.MVC بواجهة أمامية Angular 4.1.x بدأنا في استخراج بعض المكونات منها لإنشاء مكتبة مشتركة بحيث يمكن استخدامها في مشاريع أخرى.

تم إنشاء مشروع المكتبة باستخدام VS Code ويستخدم rollup لبناء إصدارات es2015 و es5 و umd في مجلد dist مع ملفات d.ts المناسبة.

تبدو النتيجة النهائية كما يلي:

-- 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

لقد ربطت npm مجلد dist / mylib بالمجلد بمشروع VS 2015 / Angular 4.1.x.

عندما أحاول تجميع المشروع في VS 2015 ، أحصل على نفس النوع من الرسائل كما هو موضح في بعض المواقف المذكورة أعلاه للاشتراك ، يمكن ملاحظته ، إلخ.

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

إذا قمت بحذف دليل node_modules مؤقتًا من مشروع المكتبة ، فإنني أحصل على أخطاء جديدة تشكو من عدم القدرة على العثور على وحدات:

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

وهو ما يقودني إلى استنتاج مفاده أنه عندما يقوم المترجم المنسوخ برمجيًا بتجميع التطبيق ، فإنه يبحث بالفعل في مجلد node_modules من حزمة المكتبة المرتبطة الخاصة بي لتعريفات الوحدات النمطية لمكتبتي وليس مجلد التطبيقات node_modules.

ليس من الواضح بالنسبة لي أي حل (حلول) مقترح أعلاه سيوفر حلاً لهذه المشكلة ، فهل يمكن لشخص ما مساعدتي؟

شكر!

mikehutter في مشروعك الذي يستخدم مكتبتك (وليس في المكتبة نفسها) ، افعل شيئًا كهذا في tsconfig:

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

قد تحتاج إلى بعض التعديل الطفيف على هذا اعتمادًا على مكان نتيجة tsconfig وشفرة المصدر.

(مثل الآخرين في هذا الموضوع ، أود أن أرى بعض التحسينات في TypeScript مما يجعل هذا غير ضروري.)

mikehutter أضفنا مؤخرًا بعض الإرشادات في Angular CLI للعمل مع libs المرتبطة ، ويبدو أنك في حالتك تفتقد تكوين مسارات TypeScript لـ RxJs في تطبيق المستهلك الخاص بك. راجع https://github.com/angular/angular-cli/blob/master/docs/documentation/stories/linked-library.md لمزيد من المعلومات.

kylecordes على النقطة 👍

شكرا لك kylecordes و @ filipesilva! كان هذا كل ما احتاجه ...

مرحبا!

mhegazy ، هل تعتقد أن هذا سيصل إلى 2.4 أم من المحتمل أن يتأخر مرة أخرى؟
هذا أمر مؤلم حقًا للتغلب عليه ، مما يجبر كل مشروع دائمًا على تحديد تعيينات المسار للأشياء التي لا ينبغي حقًا الاهتمام بها.

أتمنى حقًا هذه المرة أن يدخل هذا الإصدار في الإصدار!

الأفضل،

لا تعتقد أن هذا قد تم ذكره حتى الآن ، ولكن الطريقة المختصرة للغاية لحل هذه المشكلة هي:

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

يشير الإدخال أعلاه paths بشكل أساسي: لأي وحدة نمطية ، ابحث عنها أولاً في المجلد node_modules في جذر المشروع ، ثم الرجوع إلى القاعدة العادية (السير المتكرر للأدلة من حيث حدث الاستيراد).

(من فضلك صححني إذا كنت مخطئا ، ما زلت وافدا جديدا نسبيا إلى TS).

يبدو الإدخال في paths متعلقًا بـ baseUrl . لذلك ، إذا قمت بتعيين baseUrl ليكون في مجلد فرعي ، فستحتاج إلى تغيير تعريف المسارات وفقًا لذلك. على سبيل المثال:

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

fiznool fyi هذا جزء من خياراتي البديلة 2 و 3 (في paths ليس كافيًا إذا كان لديك مشاريع مرتبطة بالرموز تستخدم نفس الأنواع.

jasonswearingen منشورك أكثر شمولاً من لتوضيح ذلك. سأكون متأكدًا من الرجوع إليها إذا واجهت أي مشكلات أخرى. 😄

نشهد هذا أيضًا في مشروعات Google. كما هو موضح هنا:
https://github.com/Microsoft/TypeScript/issues/9091#issuecomment -306969543

لا يبدو أن الحلول الموضحة أعلاه باستخدام baseUrl والمسارات تعمل ، ولا يزال tsc يلتقط التعريفات المكررة ولا يوجد مجموعة من المسارات / baseUrl / include / Exclusion / etc. تمكنت من إقناعها بخلاف ذلك.

لدي فضول حول كيفية عمل ذلك بشكل طبيعي ، إذا كان لديك مشروع يعتمد على X ، ويعتمد أيضًا على Y الذي يعتمد بشكل انتقالي على X ، فكيف تتجنب tsc تحميل تعريفات النوع مرتين؟

esprehn أوصي بشدة بقراءة منشور الحل البديل الخاص بي هنا: https://github.com/Microsoft/TypeScript/issues/6496#issuecomment -302886203

فيما يتعلق بهذا الارتباط ، يتطلب كلا الحلين (2 و 3) أكثر من مجرد تعيين baseUrl والمسارات ، لذلك إذا كان هذا كل ما تفعله ، فيرجى إعادة قراءته. الطريقة "السهلة" هي الحل 2 ، لكني أفضل الحل 3 لأنه يسمح "بالانتقال إلى التعريف" المناسب عبر الاستوديو المرئي. مشكلة الحل 3 هي أنك تحتاج فقط إلى تحميل تعريفات d.ts الخارجية مرة واحدة في سلسلة التبعية.

امل ان يساعد.

+1 أنا أستخدم lerna ويتم تمييز اعتماد فرعي مع الأنواع المضمنة على أنه "مكرر" عند تضمينه من خلال التبعيات المرتبطة.

يمكنني مشاركة الكود إذا لزم الأمر.

باستخدام WebPack كما في Angular-CLI ، اجعل حزمة Angular-CLI تلك تشير إلى الحزمة RXJS ، ثم أزل حزمة RXJS من حزمة أي مشروع آخر .json التي لا تحتاجها بسبب WebPack .

قد يحدث هذا الموقف ليس فقط مع الروابط الرمزية ، ولكن مع npm-shrinkwrap.json في التبعية مع @types/node في dependencies . يجعل Shrinkwrap npm تثبيت نسختين متطابقتين من @types/node في الحزمة الأصلية وفي الحزمة المنكمشة. يرجى الاطلاع على https://github.com/KingHenne/custom-tslint-formatters/issues/5

واجهت أيضًا هذا عند استخدام مشروع رد فعل مثبت عليه @types/react وربطه بتطبيق يستخدم أيضًا @types/react

كنت أواجه نفس المشكلة أثناء العمل مع حزم / yarn link -ed.
Rx.js ألقى خطأ: 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>'

لحسن الحظ ، لقد قمت بحلها باستخدام نفس الإصدار Rxj.s في الحزم الأصلية والمرتبطة.
لذلك ، في حالتي ، تسبب إصداران مختلفان من Rx.js حدوث المشكلة.

هذا مانع ضخم عند العمل مع monorepos. آمل حقًا ألا يتأخر هذا بعد الآن ويجد طريقه إلى 2.5.

تحرير: 😮

image

مثير للإعجاب. monorepo هو السيناريو الوحيد الذي لا يواجه فيه فريقي هذه المشكلة ، لأن الروابط الرمزية تشير كل شيء إلى مجلد حزمة مشترك.

لقد واجه فريقي هذه المشكلة بشكل متكرر عند ربط مكتباتنا الداخلية أثناء التطوير.

لقد وجدنا مؤخرًا أداة تسمى yalc تخفف من هذا الأمر جيدًا مطورة جيدة جدًا. (بصفته TL ؛ dr ، بدلاً من ربط الحزمة بأكملها ، يقوم بتشغيل البرامج النصية قبل النشر ونسخ النتيجة إلى مجلد مرتبط).

يبدو أن هذه المشكلة يتم دفعها باستمرار. نظرًا لأن هذا يؤدي بالفعل إلى تعطيل سير عمل العديد من الأشخاص ، فهل يمكننا الحصول على نوع من الإصلاح المؤقت ، مثل "تعليق التعطيل" كما هو مقترح في # 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$);

"تعليق التعطيل" ليس أفضل بكثير من مجرد القيام بأشكال في كل مكان ، وهو أمر مؤلم جدًا في مشروع كبير. أعلاه اقترحت تغيير المترجم التالي:

إذا كانت كل هذه الشروط صحيحة ، فلا تقم بالإبلاغ عن TS2345 للفصول ذات الأعضاء الخاصين:

  1. تتوافق التواقيع العامة وفقًا لطباعة بطة TypeScript المعتادة
  2. يتم تحديد الفئات في مجلدات حزمة NPM بنفس الاسم والإصدار (وفقًا لـ package.json)
  3. الفصول لها نفس المسار النسبي لوحدتها (على سبيل المثال "./lib/blah/Bdts")

إذا لم يتم استيفاء أي من هذه المعايير ، فلا بأس من الإبلاغ عن TS2345.

سيظل الإصلاح المبسط أيضًا أفضل من الوضع الحالي ، على سبيل المثال ، ضع في اعتبارك رقم 1 فقط ، ربما فقط إذا اشترك الأشخاص عبر tsconfig. يجب أن تكون رخيصة جدًا للتنفيذ.

يتميز هذا النهج بأنه مجرد تعطيل الإنذارات الكاذبة ، مع الإبقاء على الدلالات الموجودة. في حين أن اختراقات إعادة تعيين node_modules تعمل على تغيير دقة وحدة NPM بطريقة غير صحيحة (على سبيل المثال ، التسبب في حدوث خلل في الكود في المثال الافتراضي الذي قدمته ).

لأكون صريحًا ، لست متأكدًا مما إذا كان يجب أن يكون هذا "ثابتًا" في Typescript ، حيث توجد أيضًا مشكلة في JavaScript عادي: سيعيد عامل المثيل خطأ إذا كانت فئة الكائن تختلف عن الفئة المتوفرة.

وبالتالي ، فأنا أفضل أن أتطلع إلى بديل أفضل لرابط npm الذي ربما يتم ربطه بـ () ، أولاً.

هذه رؤية جيدة. هل نظرت إلى pnpm ؟ إنها خطوة صغيرة إلى الأمام من تصميم node_modules الحالي ، لكنها خطوة فعالة للغاية إذا فهمتها بشكل صحيح.

لا يتعلق الأمر فقط npm link الذي يمكن استبداله أو عدم استخدامه ، ولكنه يتعلق بوجود إصدارات متعددة من نفس الحزمة @types/xxx مثبتة في نفس الوقت ، وغالبًا ما يتم سحبها من التبعيات التي توفر إعلانات TypeScript التي تعتمد على الإعلانات القياسية، كما لي و غيرهم من الناس الإبلاغ عنها. سيزداد عدد هذه الحزم مع زيادة اعتماد TypeScript في مجتمع Node.

Yogu أعتقد أن هذا مربك الهوية والمساواة. على الرغم من أن عمليات استيراد نفس الحزمة / الإصدار من موقعين قد تمثل مثيلين مختلفين من النوع ، إلا أنهما لا يزالان متساويين في النوع.

يتبادر إلى الذهن الكود التالي (الصالح):

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

function foo (bar: a) {}

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

يجب أن ينطبق الشيء نفسه على المكتبات التي نستوردها.

يمكن أن تكون الأنواع المستوردة من الإصدارات المختلفة للمكتبات (والحزم المقابلة @types ) متساوية ومختلفة (إذا تم تحديث المكتبة ، يجب تحديث تعريف النوع أيضًا ليعكس التغييرات).

لقد دمجت للتو تغييرًا سيحاول اكتشاف الحزم المكررة بناءً على اسمها وإصدارها ، واستخدام واحدة فقط. يرجى تجربته باستخدام typescript@next عندما يتم نشر ذلك لاحقًا.

يا هلا ، شكرًا جزيلاً على إصلاح هذا! :-)

pgonzal شكرًا على المؤشر إلى pnpm ، هذا بالتأكيد يبدو مثيرًا للاهتمام!

sompylasar يعد @types/node حالة خاصة إلى حد ما ، ولكن بالنسبة إلى @types/react ، فإليك اقتراحي: ضع جميع التبعيات المطلوبة لواجهة برمجة التطبيقات الخاصة بالوحدة النمطية في peerDependencies ، ليس في dependencies . يوضح هذا أن إصدارات التبعيات يجب أن تتطابق (أو على الأقل متوافقة) بين الوحدة النمطية الأصل والتابعة. إذا كان كل من الوالدين والطفل يستخدمان التفاعل ولكنهما لا يتبادلان الكائنات من أنواع التفاعلات ، فلن تظهر هذه المشكلة هنا في المقام الأول.

harangue إذا تم الإعلان عن فئة مرتين في ملفين مختلفين ، بنفس الاسم والبنية نفسها ، فلا يزال هناك فئتان متميزتان لا تعتبرهما JavaScript متساويين. كما ذكرت ، سيظل عامل التشغيل instanceof يميز مثيلات الفئتين.

انظر هذا الكمان لمظاهرة.

هذا هو السبب في أنني أفضل حل هذا على مستوى NPM (لذلك ليس لدينا إعلانات متعددة في المقام الأول إذا لم يكن ذلك مقصودًا) بدلاً من TypeScript.

Yogu : +1: إذا كان @types/node حالة خاصة ، أي لا يمكنك تنفيذ برنامج باستخدام نسختين مختلفتين من العقد في نفس الوقت ، فسيكون إصدارًا واحدًا ، وعلى الأرجح الإصدار المحدد في حزمة المستوى الأعلى ، ربما يجب على TypeScript التعامل معها كحالة خاصة ، على سبيل المثال ، استخدم دائمًا المستوى الأعلى @types/node لكل تبعية؟

@ andy-ms شكرا لك على هذا!

يرجى تجربتها باستخدام printcript @ next عندما يتم نشر ذلك لاحقًا.

أفترض أن هذا لم يحدث بعد. لقد جربته مع اثنين من المشاريع ولكن لم يحالفني الحظ حتى الآن. سيكون من الرائع رؤية تحديث في هذا الموضوع بمجرد توفر next . @ andy-ms

يبدو أن الإصدارات اليومية قد توقفت مرة أخرى. الأخير كان: 2.5.0-dev.20170808 .

cc /DanielRosenwasser

لست متأكدًا مما إذا كان هذا مرتبطًا ، ولكن عند تجربة 2.5.1 ، يبدو أنني أرى جانبًا واحدًا فقط من الوحدة ، حتى عندما تحتوي على d.ts في مكان آخر.

إذا كان لديّ @types لشيء ما ، فلنقل @types/mongodb ولدي إعلان مخصص يمد هذه الوحدة ، أي إضافة وعد إلى الطرق ، لذلك لدي الآن @types/mongodb الذي يحتوي الوحدة النمطية mongodb ولدي ملف d.ts في مشروعي يسمى شيئًا مثل mongo-promisification.d.ts والذي يحتوي على وحدة mongodb .

إذن ، مع هذا السيناريو أعلاه ، لدي ملف يحتوي على import {somethingFromTypes} from "mongodb" وهو يشتكي من أنه لا يمكن العثور على البيانات من وحدة الأنواع ، على الرغم من وجودها وصالحة ، ولكن إذا قمت بعمل import {somethingFromMyExtendingDts} from "mongodb" فهذا يعمل غرامة.

عند التجميع ، تم إخباري للتو أن الوحدة النمطية لا تقوم بتصدير تلك الأشياء ، عندما تفعل ذلك ، فهل هذا هو السلوك المطلوب وأحتاج فقط إلى إعادة التصدير على d.ts المخصص الخاص بي أو يجب أن تأخذ في كل من الأنواع والتمديد d.ts عندي؟

أقوم بتشغيل أحدث إصدار تجريبي (Windows 10 64 بت) ولا يبدو أنه تم إصلاح هذا بالنسبة لي.

التكاثر

بناء

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

يركض

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

أ / index.ts

import { Observable } from 'rxjs/Observable';

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

ب / 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);

يركض

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>'.

grofit أعتقد أن المشكلة في حالتك هي أن لديك إعلانين عن وحدة نمطية ، حيث ما تحتاجه هو وحدة نمطية وزيادة.
يجب أن تكون قادرًا على القيام بـ mongo-promisification.d.ts مثل هذا:

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

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

بدون import ، أنت في سياق محيط وتكتب إعلانًا جديدًا ، وليس زيادة.

(مرجع كتيب )

يمكن تأكيد أن هذا يعمل معي الآن مع [email protected] . شكراً جزيلاً لـ @ andy-ms - لقد غيرت قواعد اللعبة!

واجهت نفس المشكلة ، عندما كنت أستورد Observableمن خلال مكتبة Typescript إلى مشروع angular-cli وكانت الوظائف تستخدم مقتطف الشفرة

`` function getitems (): يمكن ملاحظتها
http.get (). map (response: Response) => {
إرجاعresponse.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 سأحتاج إلى مثال كامل حتى أتمكن من إعادة إنتاج typescript@next - قد يكون لديك angular-cli على إصدار أقدم لا يحتوي على ميزة إلغاء البيانات المكررة.

لقد جربت [email protected] ولكن ما زلت أتلقى الكثير من الخطأ TS2300: المعرف المكرر.
للأسف لا يمكنني مشاركة المشروع بأكمله. لكن إليك بعض التفاصيل:
tsconfig لحزمة 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 للمشروع الرئيسي ( @croc/webclient هي الحزمة المرتبطة):

    "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 هل يمكنك اختصار مشروعك إلى مثال بسيط يوضح المشكلة؟

mhegazy ها هو
https://github.com/evil-shrike/typescript-npmlink-issue
في جذر Propject:

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

ثم في main :

npm run tsc

مرحبًا @ evil-shrike ، لقد ضاقت المشكلة إلى:
lib / tsconfig.json

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

main / tsconfig.json

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

لذلك انتهى بنا الأمر إلى تضمين كلاهما (من tsc --listFiles ):

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

نظرًا لأن node_modules يأتي من include وليس من دقة الوحدة ، لا أعتقد أننا نسمي realpath عليه ، لذلك ينتهي به الأمر كملفين مضمنين مختلفين.
من الأفضل عدم تضمين node_modules الخاص بك على أي حال ، وبدلاً من ذلك تجميعها بشكل منفصل واستيرادها بالطريقة التي تريدها مع أي حزمة خارجية أخرى.

@ andy-ms
ليس من السهل القيام بذلك. يحتوي lib المشار إليه في حالتي على الكثير من d.ts المحيط الذي يمتد على سبيل المثال للواجهات العالمية. مثل JQueryStatic:

interface JQueryStatic {
    cleanData (elems);
}

أو التصريح عن البادئات التي تم تحميلها (تتطلب js):

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

ثم في مكان ما في مصدر lib يستخدمها:

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

عندما يتم استيراد مثل هذه الوحدة (من lib) في مكان ما بشكل رئيسي ، فإنها ستفشل في التجميع.

في مصدر lib الخاص بك ، يجب عليك استخدام توجيهات /// <reference types="" /> (أو /// <reference path="" /> ) لضمان وجود الكتابات المطلوبة كلما تم استيراد مكتبتك. بهذه الطريقة لن يكون في "تضمين" ؛ عند استيراده ، ستتم إضافة الأنواع المشار إليها تلقائيًا إلى المشروع.

@ andy-ms شكرًا ، لقد قمت بإعادة تشكيل lib الخاص بي والآن يتم تجميع مشروع npm-link-ed بشكل جيد.

لست متأكدًا مما إذا كانت هذه النسخ كبيرة جدًا ولكني أحصل على نفس الشيء من تثبيت مجردة لـ CLI مع زاوية @ next و typecript @ بجوار Observable<T> !== Observable<T> :

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

يقوم Blue باستيراد واستخدام مكون وخدمة من Red

intellix هل يمكنك الحصول على مثال على أن الأخطاء باستخدام سطر الأوامر tsc ؟ من الصعب معرفة أي إصدار من الحروف المطبوعة يستخدمه ng .

@ andy-ms ما زلت أواجه هذه المشكلة. يحدث هذا بالنسبة لي عند محاولة استخدام ارتباط npm بين أي ملحقات vscode أقوم ببنائها. كلهم يستوردون vscode مما يتسبب في أخطاء المعرف المكررة.
TS Version 2.7.0-dev.20171118

بالنسبة لي ، عملت الخريطة على سبيل المثال "rxjs / *" إلى مجلد rxjs محدد داخل node_modules في قسم المسارات بملف tsconfig.
الآن كل شيء يعمل بشكل جيد مع ارتباط npm.

لقد رأيت أيضًا أن هذا يحدث عند الانتقال من ارتباط رمزي إلى غير مرتبط من رابط تحديث إصدار إلى حزمة.

راجع سؤال SO هذا أيضًا: https://stackoverflow.com/questions/38168581/observablet-is-not-a-class-derived-from-observablet

dakaraphiJoshuaKGoldberg هل يمكنك تقديم الإرشادات لإعادة إنتاج هذه السيناريوهات؟

مع السلوك الجديد ، لا يجب تضمين حزمة إذا رأينا بالفعل حزمة أخرى بنفس قيمة "الإصدار" في package.json . إذا كان لديك تثبيتات متعددة بإصدارات مختلفة ، فستحصل على نسختين مختلفتين من الوحدة. قد يفسر ذلك سبب كسر تحديث الإصدار هذا ، إذا كان يؤثر على واحد فقط من التثبيتين.

@ andy-ms المثال الذي لدي هو المستودعات التالية:

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

أستخدم تثبيت npm محلي للإشارة إلى vscode-extension-common من vscode-extension-fold

إذا قمت بسحب هذه المستودعات ، فإنها تعمل حاليًا لأن لديّ حل بديل لتعيين المسار في package.json من vscode-extension-fold . ومع ذلك ، إذا فهمت بشكل صحيح ، فلن أحتاج إلى هذا الحل.

dakaraphi شكرا! يبدو أن الخطأ يرجع إلى كتابة vscode.d.ts كإعلان عام ومحيط وليس كوحدة نمطية خارجية. لقد قمت بإنشاء Microsoft / vscode-extension-vscode # 90.

لا يزال هذا لا يعمل بالنسبة لي عندما أحاول ربط حزمتين ، كل منهما تعتمد على rxjs . أنا أستخدم [email protected] و [email protected] . كلا الحزمتين تستخدمان نفس الإصدار بالضبط. هل لديها الحل لهذا؟

SamVerschueren هل يمكنك تقديم إرشادات محددة لإعادة إنتاج الخطأ؟ اختبر أيضًا باستخدام typescript@next .

@ andy-ms سأرى ما يمكنني فعله!

@ andy-ms إليك مستودع استنساخ صغير https://github.com/SamVerschueren/ts-link-6496. لقد استخدمت [email protected] لإعادة إنتاج هذا.

  1. قم بتثبيت كل من التبعيات لـ mod-a و mod-b
  2. تجميع mod-b بـ yarn build
  3. جمع mod-a بـ yarn build

ستفشل الخطوة 3 مع الخطأ التالي

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.

لا تزال تواجه هذه المشكلة مع مطبوعة @ next ولديها نفس المشكلة.

يبدو أن جذر المشكلة هو أن الحزم المرتبطة لا تزال تشير إلى تعريفات النوع في node_modules المحلي الخاص بها بدلاً من استخدام الكتابة من node_modules التي ترتبط بها ، عندما يكون ذلك ممكنًا. يترافق ذلك مع حقيقة أن:

  1. لا يمكن إعادة تعريف الكرة الأرضية

    • يؤدي هذا إلى شكوى المحول البرمجي عندما يتم تحديد العمومية في كل من node_modules للمشروع الأصلي وكذلك node_modules في الحزمة المرتبطة

  2. لا يمكن تخصيص الفئات التي تكون متطابقة لبعضها البعض

    • يتسبب هذا في شكوى المحول البرمجي عند محاولة تعيين متغير نوعه فئة من node_modules للمشروع الرئيسي إلى قيمة تعيدها الحزمة المرتبطة التي تم تحديد نوعها في node_modules

لقد تمكنت من التغلب على هذه المشكلة باستخدام متغير التكوين paths . بالنسبة للوحدات التي تأتي تعريفاتها من @types/* ، كما هو مقترح هنا ، يمكنك ببساطة استخدام:

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

في حالة مواجهة هذه المشكلة مع حزمة تأتي مجمعة مع تعريفات النوع التي تحدد الفئات أو الكرات الأرضية ، يجب عليك إضافتها يدويًا. على سبيل المثال ، rxjs :

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

أواجه أيضًا مشكلات مع الارتباطات الرمزية عند إضافة حزمة محلية ، باستخدام TS 2.8.3:

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

منذ الإصدار 3 ، يبدو أن npm يقوم بتثبيت هذه الروابط الرمزية بدلاً من نسخ الملفات.

ومع ذلك ، عندما أحاول التحويل البرمجي ، يرى المترجم ملف التعريف المرتبط كملفين منفصلين ومتضاربين:

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'.

إذا قمت بنسخ الملفات يدويًا بدلاً من ذلك ، فستعمل كما هو متوقع. يمكنني التغلب على هذا عن طريق تعيين typeRoots: ["./node_modules/**/"]

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات