Tslint: 'no-inferrable-types'と 'typedef'のルールが競合しています

作成日 2015年10月03日  ·  33コメント  ·  ソース: palantir/tslint

また会ったね、

これが問題なのか設計上の決定なのかはわかりませんが、ルールno-inferrebale-typestypedefの間に矛盾が見られます。

元。

function fn(): void {
    for (let i = 0; i < 100; i++) {
        console.log(i);
    }
}

https://github.com/palantir/tslint/blob/master/docs/sample.tslint.jsonからのスニペット:

 "typedef": [true, ...],
 "no-inferrable-types": true,

これらの2つのルールをオンにすると、次のようになります。

error (typedef) test.ts[2, 12]: expected variable-declaration: 'i' to have a typedef

タイプ注釈numberを変数iに追加すると、次のエラーが発生します。

error (no-inferrable-types) test.ts[2, 14]: LHS type (number) inferred by RHS expression, remove type annotation

これらの2つのルールを共存させる方法はありますか?

たとえば、プリミティブ型で直接宣言された推論可能な変数が必要です(ルールドキュメントによると、 numberboolean 、またはstring )が、その一方で、非プリミティブ型にtypedefを強制します。

ありがとう、

O。

P1 Enhancement 🌹 R.I.P. 🌹

最も参考になるコメント

:+1:理想的には(imo)「型が推測できない限り、常にtypedefが必要」という言い方をしたいと思います。 今は不可能だと思います。

全てのコメント33件

良いキャッチ、ヘッズアップをありがとう。 $#$ 1 typedef #$ルールとどのように競合するかを考えずに、 no-inferrable-typesルールを追加しました。 今のところ、2つのうちの1つをオフにするか、 typedefルールの一部のオプションのみを使用することをお勧めします。

長期的には、 no-inferrable-typestypedefルールに統合するか、少なくともTSLintに両方のルールをオンにするなどの競合する構成を検出させる必要があると思います。

私は同じ問題に直面しています。
今のところ、no-inferrable-typesをオフにしました。

はい、ここでも同じですが、両方のルールを共存させることができるようにしたいと思います。
変数の型を推測できるのであれば、typedefルールを開始したくありません。
つまり、「no-inferrable-types」は「typedef」よりも優先される必要があります

+1

let id: number = 0;
for (let job: string of NAMES_PROFFESSIONS) {
     /** some code */
     id++;
}

(no-inferrable-types)RHS式によって推測されるLHSタイプ(数値)、タイプ注釈を削除

+1

「不可解な」タイプの定義には、コンストラクターの割り当てが含まれていますか?

// BAD (this hurts my eyes to read)
let labels: Map<string, string> = new Map<string, string>();
// GOOD (type is obvious)
let labels = new Map<string, string>();

だけでなく...

// BAD (in a diff, it's not obvious what this type is)
let labels = this.buildLabels();
// GOOD
let labels: Map<string, string> = this.buildLabels();

はい、危険です。 コードを単純化し、直接初期化された変数に型宣言を使用しないようにしたい場合、これを厳密に行うことはできません。これにより、次のようなことが起こります。

let x = 2;
let y;
let z: number;

x = 1;
y = 1;
z = 1;
x = 's'; // Type 'string' is not assignable to type 'number'
y = 's'; // It's OK
z = 's'; // Type 'string' is not assignable to type 'number'

初期化された変数に対してのみスキップ型宣言を許可することは非常に便利なオプションかもしれません。

…そして@pgonzalが言うように、実際にはプリミティブ型だけではありません!
これを見てください、それはひどいです:

const onChange: () => void = () => this.update();

:+1:理想的には(imo)「型が推測できない限り、常にtypedefが必要」という言い方をしたいと思います。 今は不可能だと思います。

私はこれに遭遇し、私の場合に役立つignore-paramsフラグを作成しました。 簡単に推測できる場合でも、すべてのメソッド/関数パラメーターに対してtypedefを強制したいと思います。

試してみたい場合はPR:#1190を参照してください

元の号が提出されてからしばらく経ちました。 この時点で、 no-inferrable-typesを無効にして、すべてにタイプを含めることをお勧めしますか? no-inferrable-typestypedefの両方を有効にして組み合わせようとする他のことは、ハックのように見え、無意味な警告が大量に発生します。 近い将来、より良い解決策を期待しています。

@corydeppen上記の@englercjの提案に対する8つの親指に注意してください。 「ハックのようだ」というコメントで「組み合わせる」が何を意味するのかは不明です。 「 tslint.jsonで一緒に使用する」という意味であれば、そうです。ただし、 typedefoptional-inferrable-types引数を「組み合わせる」ことは、すばらしいことです(少なくとも、私たちの9人にとっては)。

これに関する最新情報を入手できますか?

これを処理する最善の方法は、 no-inferrable-typesを廃止し、オプションオブジェクトをtypedef initialized渡して、型が特定のパターンに従って推測できる場合は、型定義の欠如を無視することです。 initialized primitivescall signatures 、および開発者としてのニーズを満たすその他のパタ​​ーン。

私にとってこれはもっと理にかなっています。なぜなら、関数のタイプが何であるかを示す何かがない限り、常にtypedefが存在するはずだからです。 また、クラスで初期化されたpropertiesに推論可能な型を持たせたいが、たとえばcall signaturesには持たせたくないため、これも構成可能です。

誰かがこれを修正するために売り込むことができれば素晴らしいでしょう。 それまでは、「読み取りに十分な型宣言がない」か「型宣言が多すぎる」のどちらかを選択する必要があります。

この問題は2015年10月3日から発生しています。それ以来、私のチームは約2000のTypeScriptソースファイルを作成しましたが、それらはすべて、あまりにも多くの型宣言で雑然としています。

typedefは構成を受け入れます。 したがって、型が推測可能である場合、型定義を無視するための別の構成である可能性があります。

初期化されていない場所に入力するだけです。

問題への対処方法について明確なコンセンサスがないため、進展が見られないようです。 コメントの例: https ://github.com/theia-ide/theia/issues/356#issuecomment -319350833

どんな解決策もそのままにしておくよりはましだということに私たちは皆同意しているのではないかと思います。 この問題に関して現状に変更を加えるのが良いと思われる場合は、👍このコメントをお願いします。 この問題を修正するためのPRを作成するのに十分な知識がある場合は、私たち全員を助けてください❤️。

次のPRを受け入れます:

  • typedefにオプションを追加して、 no-inferrable-typesがタイプを提供しないと言っている場合を無視できるようにします

typedefは構成を受け入れます。 したがって、タイプが推測可能である場合、タイプ定義を無視するための別の構成である可能性があります。つまり、「初期化されていない場所でタイプするだけ」を意味します。

typedefルールは、コードベースに明示的な型定義を含めるのが好きな人向けです。 上記の動作で「初期化されていない場所に入力するだけ」が必要な場合は、 typedefを無効にし、TypeScriptコンパイラオプションとしてnoImplictAnyが有効になっていることを確認することをお勧めします。

次のスニペットのように、初期化されるものの中には、とにかくtypedefが必要なというトリッキーなケースもあります。

interface Literal {
    field: "value"
}

const literal0 = {
    field: "value",
};
const literal1: Literal = {
    field: "value",
};

const func = (obj: Literal) => { };
func(literal0);  // Error! Type 'string' is not assignable to type '"value"'.
func(literal1);

また、これは修正されましたが、 no-unnecessary-type-annotation (https://github.com/ajafff​​/tslint-consistent-codestyle/blob/)のような優れたサードパーティのルールが存在する可能性があることをお伝えしたいと思います。たとえば、master / docs / no-unnecessary-type-annotation.md)。 望ましい動作を提供する他のサードパーティのルールを知っている人がいる場合は、ここに投稿してください。正式に推奨するか、意味がある場合はコアに採用することができます。

@JKillian推薦してくれてありがとう、それが私が本当に欲しかったものだと思います。 anyタイプを避けることについての非常に良い投稿があります: 「nakedany」を使用せず、代わりに「anyinterface」を作成してください。

約:

interface Literal {
    field: "value"
}

const literal0 = {
    field: "value",
};
const literal1: Literal = {
    field: "value",
};

const func = (obj: Literal) => { };
func(literal0);  // Error! Type 'string' is not assignable to type '"value"'.
func(literal1);

これが望ましくない動作やトリッキーなケースになる可能性があるかどうかはわかりません。 obj $に値valueのプロパティfieldがあることを確認する必要があります。また、制約のように見えるプロパティでliteral0を初期化する場合でも、それを別の文字列に変更できます。

私は良いユースケースではないことを知っていますが、リテラルを使用している場合のほとんどの場合、おそらくプリミティブではなく、そのリテラルが必要です。

私は次の構成を持っています:
json "no-inferrable-types": true, "typedef": [true, "call-signature", "parameter"],
そしてこのコード:
javascript private static readonly DEVICE_UID: string = 'device_uid'; private static readonly DEVICE_PLATFORM: string = 'browser'; private static readonly AGENT_DEFAULT_ICON = 'http://localhost:3000/icon.png';

最初の2つの宣言でエラーが発生しないのはなぜですか?

@sandrocsimas興味深いですが、トピックから外れていると思います。 その問題はこの問題とは無関係であることをAFAICTします。 別の問題を開始することをお勧めします(fwiw!)。

@estaub 、はい、そうします。 typedefルールがなくても同じ動作が得られます。

@sandrocsimasは、読み取り専用プロパティであり、そのようなTypescriptはその型をリテラルとして推測するためです。 文字列として入力すると、文字列が必要であることがわかります。必ずしもそのリテラル値が含まれるとは限らず、値が静的に変化することはありません。

'require-typedef-except-inferrable'ルールがあると便利です。

@JKillianが言ったように@ FiretronP75は、TSCのnoImplicitAnyオプションにすぎません。

@michaeljotaありがとう、コンパイラのnoImplicitAnyオプションが推論可能な例外を与えることに気づいていませんでした。 ただし、コンパイルを中断する代わりに警告にするオプションと、tslintコメントフラグを設定するために、tslintに含めると便利です。

なぜこれが必要なのかはわかりますが、例としてno-unused-variablesを使用すると、TSCの対象となるユースケースがTSLintチームによってサポートされることはないと思います。 私はそれが_コンパイラエラー_と同じ_リンターエラー_ではないことを知っていますが、結局、それらは両方ともより良いコードを書くことについてです。 現在、TSCエラーが発生した場合でもコードをコンパイルして実行できるWebpackまたはParcelなどのソリューションが使用されている現在、これは実際の問題とは見なされていません。

これは最新バージョンで修正されていますか?

私はまだこれがロードマップにあるとは思いません。 TSCのnoImplicitAnyの使用を検討する必要があります

☠️TSLintの時が来ました! ☠️

TSLintは、#4534ごとにほとんどの機能要求を受け付けなくなりました。 TypeScriptコードをESLintでリントする新しい光沢のある方法については、 typescript-eslint.ioを参照してください。 ✨

皆様とのオープンソーシングは喜びでした!

🤖ビープブープ! 👉TSLintは非推奨です👈_(#4534)_そしてtypescript-eslintに切り替える必要があります! 🤖

🔒この問題は、これ以上の不必要な議論を防ぐためにロックされています。 ありがとう! 👋

このページは役に立ちましたか?
0 / 5 - 0 評価