[解決済み] Typescriptで<T>は何を意味するのですか?
質問
export declare function createEntityAdapter<T>(options?: {
selectId?: IdSelector<T>;
sortComparer?: false | Comparer<T>;
}): EntityAdapter<T>;
誰かこの意味を説明してくれませんか? 私は知っている
<>
が型アサーションであることは知っていますが、何のために
'T'
がわからない。 また、誰かがこの関数が何をしているのか説明してくれると助かります。
どのように解決するのですか?
誰か私に説明してください
<T>
は何を意味するのでしょうか?
それは、タイプスクリプト ジェネリック の宣言になります。
抜粋です。
ソフトウェア工学の主要な部分は、明確に定義された一貫性のあるAPIを持つだけでなく、再利用可能なコンポーネントを構築することです。今日のデータと明日のデータを扱うことができるコンポーネントは、大規模なソフトウェアシステムを構築するための最も柔軟な能力を与えてくれます。
C# や Java のような言語では、再利用可能なコンポーネントを作成するためのツールボックスの主要なツールの 1 つがジェネリックスです。これにより、ユーザーはこれらのコンポーネントを消費して、独自の型を使用することができます。
とおっしゃっています。
<ブロッククオートT'が何であるかは知らない。
'T'
の代わりに実行時に宣言される型になります。
コンパイル
の時に宣言された型になります。 そのため
T
変数は宣言されていない任意の変数である可能性があります(参考文献は見つかりませんでしたが、変数名に使用できる任意の有効な文字のセットを仮定します)。 同様に
c#
では、もし型
T
が値の型ではなく、より複雑な型(クラス)やインターフェイスを表している場合、以下のように命名/宣言される可能性があります。
TVehicle
または
TAnimal
を使用することで、将来のプログラマーのために有効な型を示すことができます(また、単に
T
は直感的でないからです)。私は
TSomething
の方が好きです。なぜなら、大文字のTは一般的な型を意味することが分かっているからです。
WSometing
あるいは
ASomething
も有効ですが、私はこれを好みません。 (マイクロソフトのAPIは、ほとんど常に
TContext
または
TEntity
など)。
また、この関数が何をしているのか、どなたか説明していただけると助かります。
さて、この関数は していません。 何かをしているわけではありません。 これはむしろ、複数の実行時型値を持つことができる関数の型を宣言しているのです。 それを説明する代わりに、上のリンクから直接抜粋したものを載せます。
function identity<T>(arg: T): T {
return arg;
}
のように使うことができる。
// type of output will be 'string'
let output = identity<string>("myString");
または
// type of output will be 'string', the compiler will figure out `T`
// based on the value passed in
let output = identity("myString");
または
// type of output will be 'number'
let output = identity(8675309);
という疑問が湧くかもしれません。
なぜジェネリックを使うのか
Javascriptには配列がありますが、配列から値を取り出すと、文字通り何でもありになってしまいます(typescript:
any
). typescriptでは、このように宣言することで、Type safetyを得ることができます。
// Array<T>
let list: number[] = [1, 2, 3];
// or
let list: Array<number> = [1, 2, 3];
これで配列の各値は型を持つようになりました。 Typescript はこの配列に文字列を入れようとすると、コンパイル時にエラーを投げます。 また、値を取り出す際には、型安全性とインテリセンスが得られます(エディタに依存します)。
class Person {
FirstName: string;
}
let people: Array<Person> = [];
people.push({ FirstName: "John" } as Person);
let john = people.pop();
// john is of type Person, the typescript compiler knows this
// because we've declared the people variable as an array of Person
console.log(john.FirstName);
型付き汎用制約を宣言する。の非常に良い例です。 オープン-クローズの原則 .
オブジェクト指向プログラミングにおいて、オープン/クローズの原則は、quot;ソフトウェアの実体(クラス、モジュール、関数など)は、拡張に対してはオープンであるが、修正に対してはクローズであるべきである[1]、つまり、その実体は、そのソースコードを変更することなくその動作を拡張できるようにすることである。
次の例では、誰もが Human や Cheetah を拡張したり、独自の派生型を作成したりすることができ、Logger の機能は何の変更もなく動作し続けます。
interface IAnimal {
LegCount: number;
}
class Cheetah
implements IAnimal {
LegCount: number = 4;
}
class Human
implements IAnimal {
LegCount: number = 2;
}
public class Logger<TAnimal extends IAnimal> {
public Log(animal: TAnimal) {
console.log(animal.LegCount);
}
}
var logger = new Logger();
var human = new Human();
logger.Log(human);
前の例では
一般的な制約
を制限するために
TAnimal
型のプログラマが
Logger
のインスタンスを,インターフェイスから派生した型に変換することができます.
IAnimal
. これによって、コンパイラは
Logger
クラスは常にその型がプロパティを持つことを想定しています。
LegCount
.
なぜTypescriptのドキュメントでは、例えば<Identity>のようなもっと説明的なものを置かずに、<T>を置くのか、説明してください。私にとっては、何もないのと<T>は同じです。今、誰もが馬鹿のように <T> を使っているのでしょうか、それとも私が何かを見逃しているのでしょうか?
これらはすべて、以下における仮定になります。 私はtypescriptのジェネリックシステムを設計したチームもドキュメントを書いたチームも知らないのです。
ジェネリックの根源的なレベルでは
T
として
任意の可能な型
(typescriptと混同しないように
any
). 意味
Array<T>
は
インタフェース
(言葉は悪いですが) であり、具体的な型を作成するときには、その型を
T
を宣言された型に置き換えます。
Array<number>
ということで
インターフェース
Array<T>
よりも意味があるのは
T
? わかりません。 私が知っているのは
T
は Type (数値、文字列など) でなければならないので
T
は単語の最初の文字であるため
タイプ
. と思います。
Array<Type>
は本当に紛らわしく、また無効でさえあるかもしれません。
タイプ
または
タイプ
が予約または制限されるようになりました(現在は
type
は特定の文脈で特別な意味を持つので、これも悪い選択です)ので、これらを避けることは良い選択です。 他の言語(
C-シャープ
,
ジャバ
) も選択し
T
を使うので、言語間で切り替えて同じ用語を使えるのは有利です。
翻って、次のような場合はどうでしょうか。
Array<Identity>
何が
Identity
は何でしょうか? 他の開発者や将来の開発者がそれが何であるかを知るのに役立つ制約がないのです。 私には、明示的に実装しなければならない特定の型付けされた Array に見えます。つまり、一般的な型を選択するのは私次第ではないのです。
interface Foo1 {
bars: Array<Identity>;
}
前の例では、私 (そしておそらくほとんどの開発者) は Identity が既存の型であり、それを変更することはできないと仮定しています。
interface Foo2<T> {
bars: Array<T>;
}
とは
Foo2
タイプを選択する必要があることは分かっています。
interface Foo3<Identity> {
bars: Array<Identity>;
}
Foo3
は紛らわしいだけです。
interface Foo4<TIdentity> {
bars: Array<TIdentity>;
}
では
Foo4
で、型を選択しなければならないことに確信が持てましたが、まだ少し混乱しています。
TIdentity
. 明らかに、型がより定義されているいくつかのコンテキストでは、それは意味をなさないでしょう。
編集する
2021年3月の時点で
タイプスクリプト・ドキュメント
の使用を非推奨とするために更新されました。
<T>
の使用を非推奨とし、代わりに
<Type>
.
ということで、私は
個人的に
は紛らわしいと思うので、次のようなものは避けることを強くお勧めします。
Type
を避けることを強くお勧めします。
interface Lengthwise {
length: number;
}
function loggingIdentity<Type extends Lengthwise>(arg: Type): Type {
console.log(arg.length);
return arg;
}
型名に名前をつけない理由の第一は
Type
を使用しない最初の理由は、メソッド内または複数のメソッドであまりうまく読み取れないことです。 ロギング・メソッドが2行よりはるかに長く、突然、読んでいるものがすべて、単語
Type
という単語がいたるところにあります。
interface Lengthwise {
length: number;
}
interface Widthwise {
width: number;
}
function loggingLength<Type extends Lengthwise>(arg: Type): Type {
console.log(arg.length);
return arg;
}
function loggingWidth<Type extends Widthwise >(arg: Type): Type {
console.log(arg.width);
return arg;
}
以下の方が読みやすいと思います。
interface Lengthwise {
length: number;
}
interface Widthwise {
width: number;
}
function loggingLength<TLengthwise extends Lengthwise>(arg: TLengthwise): TLengthwise {
console.log(arg.length);
return arg;
}
function loggingWidth<TWidthwise extends Lengthwise>(arg: TWidthwise ): TWidthwise {
console.log(arg.length);
return arg;
}
次に、1つ以上のジェネリックを持つことは非常に可能であり、それは以下のことを無効にしています(明白な理由であることを望みます)。
interface Lengthwise {
length: number;
}
interface Widthwise {
width: number;
}
function loggingLength<Type extends Lengthwise, Type extends Widthwise>
(arg1: Type, arg2: Type) {
console.log(arg1.length);
console.log(arg2.width);
}
ドキュメントでは
Type
を使用していますが、私は
Type
を使わないことを強くお勧めします。
関連
-
[解決済み】Typescriptで、! (エクスクラメーションマーク/バン)演算子でメンバを再参照するのは?
-
[解決済み】tsconfigファイルにおけるesModuleInteropの理解
-
[解決済み] TypeScriptで文字列を数値に変換する方法とは?
-
[解決済み] TypeScript で `window` に新しいプロパティを明示的に設定するにはどうすればよいですか?
-
[解決済み] TypeScriptでの取得と設定
-
[解決済み] TypeScriptでパラメータとして強く型付けされた関数は可能か?
-
[解決済み】TypeScriptのインターフェースと型について
-
[解決済み】Typescript インターフェースのデフォルト値
-
[解決済み] ts ES5/ES3の非同期関数やメソッドには、「Promise」コンストラクタが必要です。
-
[解決済み] モジュールと名前空間 - Import vs Require Typescript
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] TypeScriptの予約語 "type "とは何ですか?
-
[解決済み] Typescriptでインターフェースやクラスを使用する場合 [重複].
-
[解決済み] ユニオン型からインターセクション型への変換
-
[解決済み] Angular 2でアプリ起動時にサービスを実行する方法
-
[解決済み] Typescript のプリミティブ型:"number" と "Number" の違い(TSC は大文字と小文字を区別しない)?
-
[解決済み] TypeScriptでObject.keysがkeyof型を返さないのはなぜですか?
-
[解決済み] Visual Studio コード自動インポート
-
[解決済み] ngForとAsync Pipe Angular 2でObservableオブジェクトから配列を利用する。
-
[解決済み] TypeScriptで強く型付けされた配列の作成
-
[解決済み] 2つのインターフェイスを統合する