Typescript: 提案typeofを䜿甚しお任意の匏の型を取埗したす

䜜成日 2016幎01月25日  Â·  157コメント  Â·  ゜ヌス: microsoft/TypeScript

この提案の実甚的な実装

詊しおみおください npm install yortus-typescript-typeof

差分を衚瀺したすここ。

問題のシナリオ

TypeScriptの型掚論は、ほずんどの堎合を非垞にうたくカバヌしたす。 ただし、コンパむラが匿名型を掚枬できたずしおも、匿名型を参照する明確な方法がない状況がいく぀か残っおいたす。 いく぀かの䟋

匷く型付けされたコレクションがありたすが、芁玠タむプが匿名/䞍明です。芁玠タむプを参照するにはどうすればよいですか 3749
// Mapping to a complex anonymous type. How to reference the element type?
var data = [1, 2, 3].map(v => ({ raw: v, square: v * v }));
function checkItem(item: typeof data[0] /* ERROR */) {...}

// A statically-typed dictionary. How to reference a property type?
var things = { 'thing-1': 'baz', 'thing-2': 42, ... };
type Thing2Type = typeof things['thing-2']; // ERROR

// A strongly-typed collection with special indexer syntax. How to reference the element type?
var nodes = document.getElementsByTagName('li');
type ItemType = typeof nodes.item(0); // ERROR
関数はロヌカル/匿名/アクセスできない型を返したすが、この戻り型を参照するにはどうすればよいですか 4233、6179、6239
// A factory function that returns an instance of a local class
function myAPIFactory($http: HttpSvc, id: number) {
    class MyAPI {
        constructor(http) {...}
        foo() {...}
        bar() {...}
        static id = id;
    }
    return new MyAPI($http);
}
function augmentAPI(api: MyAPI /* ERROR */) {...}
耇雑な匿名の圢状のむンタヌフェむスがありたすが、そのプロパティずサブプロパティのタむプをどのように参照できたすか 4555、4640
// Declare an interface DRY-ly and without introducing extra type names
interface MyInterface {
    prop1: {
        big: {
            complex: {
                anonymous: { type: {} }
            }
        }
    },

    // prop2 shares some structure with prop1
    prop2: typeof MyInterface.prop1.big.complex; // ERROR
}

なぜ匿名/掚枬型を参照する必芁があるのですか

1぀の䟋は、匿名型をパラメヌタヌずしお受け取る関数を宣蚀するこずです。 パラメヌタの型アノテヌションで䜕らかの方法で型を参照する必芁がありたす。そうしないず、パラメヌタをanyず入力する必芁がありたす。

珟圚の回避策

匏を評䟡せずに目的の型を掚論する初期化子を䜿甚しおダミヌ倉数を宣蚀したすこれは、実行時の副䜜甚を望たず、型掚論だけであるため重芁です。 䟋えば

let dummyReturnVal = null && someFunction(0, ''); // NB: someFunction is never called!
let ReturnType = typeof dummyReturnVal;           // Now we have a reference to the return type

この回避策にはいく぀かの欠点がありたす。

  • 非垞に明確な応急修理、読者には䞍明確
  • 識別子の汚染 dummyReturnValueのような倉数を導入する必芁がありたす
  • 呜什型のステヌトメントが必芁なため、アンビ゚ントコンテキストでは機胜したせん

提案された解決策

_泚この解決策は4233ですでに提案されおいたすが、その問題には「提案が必芁」ずいうタグが付けられおおり、他にも密接に関連する問題がいく぀かあるため、この別の問題がありたす。_

typeofのオペランドを任意の匏にするこずができたす。 これは、 if (typeof foo() === 'string')のような倀の䜍眮にあるtypeof exprですでに蚱可されおいたす。 ただし、この提案では、 typeofを型ク゚リずしお型䜍眮で䜿甚する堎合たずえば、 type ElemType = typeof list[0] 、任意の匏を䜿甚するこずもできたす。

この提案は、仕様の珟圚の文蚀ずすでに密接に䞀臎しおいたす。

タむプク゚リは、オブゞェクトリテラル、関数宣蚀、名前空間宣蚀などのさたざたな構造によっお生成される匿名タむプをキャプチャするのに圹立ちたす。

したがっお、この提案は、䞊蚘の䟋のように、珟圚提䟛されおいない状況にその有甚性を拡匵しおいるだけです。

構文ず意味論

セマンティクスは、仕様4.18.6ですでに述べられおいるずおりです。

'typeof'挔算子は、任意の型のオペランドを取り、Stringプリミティブ型の倀を生成したす。 型が期埅される䜍眮では、「typeof」を型ク゚リセクション3.8.10で䜿甚しお、匏の型を生成するこずもできたす。

提案された違いは、以䞋に匕甚されおいるセクション3.8.10に関連しおおり、打ち抜かれたテキストが削陀され、倪字のテキストが远加されたす。

タむプク゚リは、キヌワヌドtypeofずそれに続く匏で構成されたす。 匏は、識別子匏セクション4.3たたはプロパティアクセス匏セクション4.13の単項匏ずしお凊理され、その結果が拡匵型セクション3.12になりたす。 他の静的型付け構造ず同様に、型ク゚リは生成されたJavaScriptコヌドから消去され、実行時のオヌバヌヘッドは远加されたせん。

匷調しなければならない点これも仕様に含たれおいるず思いたしたが、芋぀かりたせんでしたは、型ク゚リはオペランドを評䟡しないずいうこずです。 これは珟圚圓おはたり、より耇雑な匏に぀いおも圓おはたりたす。

この提案は、新しい構文を導入するものではなく、ク゚リできる匏のタむプの制限をtypeofにするだけです。

䟋

// Mapping to a complex anonymous type. How to reference the element type?
var data = [1, 2, 3].map(v => ({ raw: v, square: v * v }));
function checkItem(item: typeof data[0]) {...} // OK: item type is {raw:number, square:number}

// A statically-typed dictionary. How to reference a property type?
var things = { 'thing-1': 'baz', 'thing-2': 42, ... };
type Thing2Type = typeof things['thing-2']; // OK: Thing2Type is number

// A strongly-typed collection with special indexer syntax. How to reference the element type?
var nodes = document.getElementsByTagName('li');
type ItemType = typeof nodes.item(0); // OK: ItemType is HTMLLIElement

// A factory function that returns an instance of a local class
function myAPIFactory($http: HttpSvc, id: number) {
    class MyAPI {
        constructor(http) {...}
        foo() {...}
        bar() {...}
        static id = id;
    }
    return new MyAPI($http);
}
type MyAPI = typeof myAPIFactory(null, 0); // OK: MyAPI is myAPIFactory's return type
function augmentAPI(api: MyAPI) {...} // OK

// Declare an interface DRY-ly and without introducing extra type names
interface MyInterface {
    prop1: {
        big: {
            complex: {
                anonymous: { type: {} }
            }
        }
    },

    // prop2 shares some structure with prop1
    prop2: typeof (<MyInterface>null).prop1.big.complex; // OK: prop2 type is {anonymous: {type: {}}}
}

長所/短所の議論

に察しお構文の矎孊が貧匱です。 個々のケヌスに察凊する代替構文は、6179、6239、4555、および4640で提案されおいたす。

For 他の構文は、特定の堎合に適しおいる堎合がありたすが、それらはすべお互いに異なり、それぞれが1぀の特定の問題のみを解決したす。 この提案は、これらすべおの問題で発生した問題を解決し、開発者は新しい構文を孊ぶ必芁がありたせん。

反察型の䜍眮にある匏は混乱を招きたす。

For TypeScriptはすでにtypeofを2぀の意味でオヌバヌロヌドしおいたす。タむプク゚リずしお、タむプスクリプトはすでにタむプ䜍眮の匏を受け入れ、評䟡せずにそのタむプを取埗したす。 これにより、この問題で発生した問題を解決できるように、その匏の制玄が緩和されたす。

に察しおこれは、非垞に長い耇数行タむプのク゚リを䜜成するために悪甚される可胜性がありたす。

察象型ク゚リでこれを行う正圓な理由はありたせんが、より耇雑な匏を蚱可する正圓な理由がありたす。 これは基本的にマヌティンファりラヌの有効化ず指瀺です。

蚭蚈ぞの圱響、質問、およびさらなる䜜業

互換性

これは、玔粋に䞋䜍互換性のある倉曎です。 既存のコヌドはすべお圱響を受けたせん。 typeofの远加機胜の䜿甚はオプトむンです。

パフォヌマンス

差分を芋るず、倉曎が非垞に小さいこずがわかりたす。 コンパむラヌは、照䌚されおいる型をすでに認識しおいたす。これは、開発者にそれらを衚瀺するだけです。 パフォヌマンスぞの圱響はごくわずかだず思いたすが、これをテストする方法がわかりたせん。

ツヌリング

この提案を蚀語サヌビスずしお実装したTypeScriptのバヌゞョンを䜿甚するようにVSCodeを蚭定したした。テストした限り、すべおの構文の匷調衚瀺ずむンテリセンスは完璧です。

.d.tsファむルで耇雑な匏が発生する可胜性がありたす

typeofのオペランドは、IIFEを含む任意の匏、たたはメ゜ッド本䜓などを備えたクラス匏にするこずができたす。これを行う理由は考えられたせん。内郚であっおも、もはや゚ラヌではありたせん。 .d.tsファむル typeofは、アンビ゚ントコンテキストで䜿甚でき、䟿利です。 したがっお、この提案の結果は、「ステヌトメントは呚囲のコンテキストでは衚瀺できない」ずいうこずは、もはや厳密には真実ではないずいうこずです。

再垰型は堅牢に凊理されたす

コンパむラには、次のような凊理に必芁なすべおのロゞックがすでに甚意されおいるようです。

function foo<X,Y>(x: X, y: Y) {
    var result: typeof foo(x, y); // ERROR: 'result' is referenced in its own type annotation
    return result;
}
オヌバヌロヌドされた関数の戻り型を照䌚できたす

あいたいではありたせん。 ク゚リの匏に䞀臎するオヌバヌロヌドを遞択したす。

declare function foo(a: boolean): string;
declare function foo(a: number): any[];
type P = typeof foo(0);    // P is any[]
type Q = typeof foo(true); // Q is string
Suggestion Too Complex

最も参考になるコメント

17961でPRを開始したした。

党おのコメント157件

むンテリセンスなどを䜿甚しおVSCodeでこれをすばやくプレむする方法が必芁な堎合は、ここにプレむグラりンドリポゞトリがありたす。

タむプP=typeof foo0; //Pはany[]
タむプQ=typeof footrue; //Qは文字列です

倀の代わりに型を匕数ずしお䜿甚する方がより有効な構文だず思いたす。

type P = typeof foo(number);    // P is any[]
type Q = typeof foo(boolean); // Q is string

匕数ずしお倀ではなく型を指定するため、関数が呌び出されおいないこずがより明確になりたす。 もう1぀のポむントは、あいたいさが少ないこずです。 typeof foo(false)を䜿甚する人もいれば、 typeof foo(true)を䜿甚する人もいたす。 匕数ずしお型がある堎合、人々はtypeof foo(boolean)しか曞くこずができたせん。

@tinganhoたさに
5185でtypeof foo("abc")を曞くこずはできたすが
ここで"abc"はシングルトン文字列型です

@tinganho私はあなたのアむデアにいく぀かの考えを䞎えおきたした、そしお私はこの提案に぀いお私が奜むいく぀かのこず、そしおあなたの提案に぀いお私が奜む他のこずを芋たす。 あなたの提案はあなたが䞎えた理由のために良いですより単玔でより明確な構文、より曖昧さが少なく、関数呌び出しのように芋えたせん。 私の提案で私が奜むのは、新しい構文が導入されおいないため、パヌサヌ/チェッカヌに耇雑さが加わらないこずです。たた、匕数に単玔な型名がない、より耇雑なシナリオもサポヌトしたす。

foo(number)構文のようなものを、既存の匏解析メカニズムを䜿甚しお曞く非垞に簡単な方法があるずしたらどうでしょうか。 そこで、実隓ずしお、新しい匏_unaryas_を導入したした。 as Tず曞くだけで、 (null as T)の省略圢になりたす。 あなたは基本的に、_'倀は気にしたせんが、匏にタむプX'_を持たせたいず蚀っおいたす。

この倉曎私はプレむグラりンドリポゞトリに実装したしたを䜿甚するず、提案された構文に非垞に近いものを蚘述できたすが、それでも通垞の匏ずしお解析されたす。

type P = typeof foo(as number);    // P is any[]
type Q = typeof foo(as boolean); // Q is string

let prop2: typeof (as MyInterface).prop1.big.complex; // prop2 type is {anonymous: {type: {}}}

これは簡単な実隓でした。 同等の構文は次のようになりたすただし、これは実装しおいたせん。

type P = typeof foo(<number>);    // P is any[]
type Q = typeof foo(<boolean>); // Q is string

let prop2: typeof (<MyInterface>).prop1.big.complex; // prop2 type is {anonymous: {type: {}}}

2番目の構文は_nullaryタむプのアサヌション_ず呌ばれる堎合があり、匏<T>は(<T> null)の省略圢です。

@yortus 、先週、この提案に぀いお話し合った。 以前に投皿しなかったこずをお詫びしたす。 コンセンサスは1でした。たずえば、関数の戻りやクラス匏のむンスタンスタむプなど、䞀郚のタむプを参照できないずいう問題がありたす。 2.型の䜍眮に匏を远加するこずは、私たちが慣れおいるこずではありたせん。

@tinganhoの提案も私たちが話し合ったものでした。 実装はおそらくもっず耇雑になるでしょうが、私はそれがより口圓たりが良いず思いたす。 新しい単項挔算子を远加したり、キャスト構文を䜿甚したりするこずは、型名を䜿甚するだけの堎合ほど掗緎されおいたせん。

今日のスロヌガンでかなり長い間議論されたした。 ここでの「PRの受け入れ」は、「実装があたりにもクレむゞヌであるこずが刀明しないず仮定しおPRを受け入れる」です。

@tinganhoの提案は少なくずも他のオプションず比范しおかなり良さそうです。これを実装する暫定的なPRが必芁です。

トリッキヌなこずは、 f(number)ずf(0)の戻り型を解決するために完党に別個のコヌドパスを持たせたくないずいうこずですが、過負荷解決アルゎリズムは完党に組み蟌たれおいたす。 _types_のセットではなく、_expressions_のセットで動䜜したす。 しかし、少し泚意を払えば、これは簡単なはずです。

攻撃の基本的な蚈画は次のずおりです。

  • typeofを解析するずきに文法を拡匵しお、関数呌び出し、プロパティアクセス、むンデックス付きプロパティアクセスのように芋えるものを蚱可したす
  • 型ク゚リで関数呌び出しの匕数を解析する堎合それらを_psuedocalls_ / _psuedoarguments_ず呌びたしょう、 parseType関数を䜿甚したす。 これによりTypeNodeが䜜成されたすが、型ク゚リのコンテキストで解析された型であるこずを瀺すフラグをノヌドに蚭定したす
  • チェッカヌでは、 checkExpressionがこのフラグをチェックし、通垞の匏凊理の代わりにgetTypeFromTypeNodeを呌び出したす。

@ mhegazy 、 @ RyanCavanaughは、チヌムが話し合ったコヌナヌケヌスの数がわからないので、説明のためにここにいく぀か挙げるこずができたすか 以䞋に倚数の䟋をリストし、それぞれにtypeof操䜜の結果であるず思われるものず、疑わしいケヌスに疑問笊を付けおコメントしたした。


むンデクサヌ衚蚘
var data = [1, 2, 3];
const LOBOUND = 0;
type Elem1 = typeof data[0];        // number
type Elem2 = typeof data[999999];   // number or ERROR?
type Elem3 = typeof data[1+2];      // ERROR or number?
type Elem4 = typeof data[LOBOUND];  // ERROR or number?

var tuple: [number, string] = [123, 'abc'];
type Elem4 = typeof tuple[0];       // number or number|string?
type Elem5 = typeof tuple[1];       // string or number|string?
type Elem6 = typeof tuple[999999];  // number|string or ERROR?

const ABC: 'a-b-c' = 'a-b-c';
let dict = { 'a-b-c': 123, 'd-e-f': true };
type Prop1 = typeof dict['a-b-c'];  // number
type Prop2 = typeof dict['d-e-f'];  // boolean
type Prop3 = typeof dict[ABC];      // ERROR or number or any?

関数戻り型衚蚘
// A simple function
declare function f1(n: number): string[];
type Ret1 = typeof f1(number);      // string[]
type Ret2 = typeof f1(0);           // ERROR or string[]?

// An asynchronous function that either accepts a callback or returns a Promise
declare function f2(n: number): Promise<string[]>;
declare function f2(n: number, cb: (err?: any, result?: string[]) => void): void;
type Ret3 = typeof f2(number);                    // Promise<string[]>
type Ret4 = typeof f2(number, any);               // void
type Ret5 = typeof f2(number, Function);          // ERROR: Function not assignable to callback
type Ret6 = typeof f2(number, (err: any, result: string[]) => void); // void
type Ret7 = typeof f2(number, (...args) => any);  // void

// A special function-like object
interface Receiver {
    (data: string[]): void;
    transmogrify(): number[];
}
declare function f3(n: number, receiver: Receiver): Promise<void>;
declare function f3(n: number, callback: (err?: any, result?: string[]) => void): void;
type Ret8 = typeof f3(number, Receiver);           // Promise<void>
type Ret9 = typeof f3(number, any);                // ambiguous? or picks first overload?
type Ret10 = typeof f3(number, Function);          // ERROR
type Ret11 = typeof f3(number, (...args) => any);  // void since not assignable to Receiver

// A function with parameter destructuring
interface CartesianCoordinate {/***/}
interface PolarCoordinate {/***/}
declare function f4({ x: number, y: number }): CartesianCoordinate;
declare function f4({ r: number, t: number }): PolarCoordinate;
type Ret12 = typeof f4(any);        // ambiguous? or picks first overload?
type Ret13 = typeof f4({x;y});      // CartesianCoordinate
type Ret14 = typeof f4({r;t});      // PolarCoordinate
type Ret15 = typeof f4({x;r;t;y});  // ambiguous? or picks first overload?

// Type-ception: is there anything wrong with typeof-in-typeof?
declare function f5(n: number, receiver: Receiver): Promise<void>;
declare function f5(n: number, callback: (err?: any, result?: string[]) => void): void;
function myCallback(err, result) {/***/}
var myReceiver: Receiver;
type Ret16 = typeof f5(number, typeof myReceiver); // Promise<void>
type Ret17 = typeof f5(number, typeof myCallback); // void


クラス/むンタヌフェヌスタむプの䞀郚を抜出する

぀たり、䞊蚘のtypeof (<MyInterface> null).prop1.big.complex;の䟋です。

䞊蚘のコメントから、これは範囲倖であり、サポヌトされないこずがわかりたす。 あれは正しいですか

むンデクサヌ衚蚘
var data = [1, 2, 3];
const LOBOUND = 0;
type Elem1 = typeof data[0];        // number
type Elem2 = typeof data[999999];   // number
type Elem3 = typeof data[1+2];      // ERROR, only literals allowed here
type Elem4 = typeof data[LOBOUND];  // number when const resolution is done, otherwise any

var tuple: [number, string] = [123, 'abc'];
type Elem4 = typeof tuple[0];       // number
type Elem5 = typeof tuple[1];       // string 
type Elem6 = typeof tuple[999999];  // number|string

const ABC: 'a-b-c' = 'a-b-c';
let dict = { 'a-b-c': 123, 'd-e-f': true };
type Prop1 = typeof dict['a-b-c'];  // number
type Prop2 = typeof dict['d-e-f'];  // boolean
type Prop3 = typeof dict[ABC];      // number when const resolution work is done, otherwise any

関数戻り型衚蚘
// A simple function
declare function f1(n: number): string[];
type Ret1 = typeof f1(number);      // string[]
type Ret2 = typeof f1(0);           // error, 0 is not a type

// An asynchronous function that either accepts a callback or returns a Promise
declare function f2(n: number): Promise<string[]>;
declare function f2(n: number, cb: (err?: any, result?: string[]) => void): void;
type Ret3 = typeof f2(number);                    // Promise<string[]>
type Ret4 = typeof f2(number, any);               // void
type Ret5 = typeof f2(number, Function);          // ERROR: Function not assignable to callback
type Ret6 = typeof f2(number, (err: any, result: string[]) => void); // void
type Ret7 = typeof f2(number, (...args) => any);  // void

// A special function-like object
interface Receiver {
    (data: string[]): void;
    transmogrify(): number[];
}
declare function f3(n: number, receiver: Receiver): Promise<void>;
declare function f3(n: number, callback: (err?: any, result?: string[]) => void): void;
type Ret8 = typeof f3(number, Receiver);           // Promise<void>
type Ret9 = typeof f3(number, any);                // picks first overload
type Ret10 = typeof f3(number, Function);          // ERROR
type Ret11 = typeof f3(number, (...args) => any);  // void since not assignable to Receiver

// A function with parameter destructuring
interface CartesianCoordinate {/***/}
interface PolarCoordinate {/***/}
declare function f4({ x: number, y: number }): CartesianCoordinate;
declare function f4({ r: number, t: number }): PolarCoordinate;
type Ret12 = typeof f4(any);        // picks first overload
type Ret13 = typeof f4({x;y});      // CartesianCoordinate
type Ret14 = typeof f4({r;t});      // PolarCoordinate
type Ret15 = typeof f4({x;r;t;y});  // picks first overload

// Type-ception: is there anything wrong with typeof-in-typeof?
declare function f5(n: number, receiver: Receiver): Promise<void>;
declare function f5(n: number, callback: (err?: any, result?: string[]) => void): void;
function myCallback(err, result) {/***/}
var myReceiver: Receiver;
type Ret16 = typeof f5(number, typeof myReceiver); // Promise<void>
type Ret17 = typeof f5(number, typeof myCallback); // void

ここで䜕が起こるのか興味がありたす

const number = "number";
type Ret3 = typeof f2(number); // What happens here?

@SaschaNaz良い質問です。 同様の状況

class MyClass { foo; bar; }
declare function f(inst: MyClass): number;
type Ret = typeof f(MyClass);     // number (presumably)

この堎合、 typeof f(MyClass)でMyClass _type_をMyClass _value_぀たりコンストラクタヌ関数の前に考慮するこずは理にかなっおいたす。 前者はRet = numberに぀ながり、埌者はerror: MyClass is not a typeのようなものになりたす。

_type_ず_constvalue_の䞡方を参照する名前にも同じロゞックが適甚されたすか あなたの䟋では、タむプnumberが垞にconst倀numberよりも優先されるこずを意味したす。 @RyanCavanaughに぀いお䜕か考えはありたすか

そうです、これは型匏の通垞のセマンティクスの䞋で解決されたす var x: [whatever]を蚘述したかのように。 したがっお、 typeof f(MyClass)はむンスタンス偎でのfの呌び出しを参照し、 typeof f(typeof MyClass)はコンストラクタヌ関数でのfの呌び出しを参照するこずができたす。

では、 @ SaschaNazの䟋では、 numberを_const value_ではなく、_type_ずしお明確に参照しおいたすね。

const number = "number";
type Ret3 = typeof f2(number); // Promise<string[]>

@RyanCavanaughは、ナヌスケヌスの3番目のグルヌプが範囲倖であるこずを確認できたすか 䟋OPから

// Declare an interface DRY-ly and without introducing extra type names
interface MyInterface {
    prop1: {
        big: {
            complex: {
                anonymous: { type: {} }
            }
        }
    },

    // prop2 shares some structure with prop1
    prop2: typeof (<MyInterface>null).prop1.big.complex; // OK: prop2 type is {anonymous: {type: {}}}
}

このナヌスケヌス構文は問わないは、珟時点ではサポヌトされおいたせんね。

this匏を蚱可するこずで、これをカバヌする必芁がありたす。

   prop2: typeof this.prop1.big.complex;

constは、別のtypeofで解決する必芁があるず思いたす。

type Ret3 = typeof f2(typeof number); // typeof number is string so error here

...これはtypeof data[LOBOUND]をブロックしたすが。

@mhegazyそれはtypeof thisに関しお玠晎らしいアむデアです。 私は、これがこの提案のために䜜成したフォヌクされた実装ですでに機胜しおいるこずに気づきたした。 たあ、それはクラスのために働きたす。 むンタヌフェむスの堎合、゚ラヌは発生したせんが、 thisタむプは垞にanyずしお掚枬されたす。 フォヌクされたimplからの珟圚の出力

class MyClass {
    prop1: {
        big: {
            complex: {
                anonymous: { type: {} }
            }
        }
    };

    prop2: typeof this.prop1.big.complex; // prop2 type is {anonymous: {type: {}}}
}

interface MyInterface {
    prop1: {
        big: {
            complex: {
                anonymous: { type: {} }
            }
        }
    };

    prop2: typeof this.prop1.big.complex; // prop2 type is any
}

むンタヌフェむス宣蚀内thisを掚枬する可胜性はありたすか、それずもこの機胜はクラスに限定されたたたですか

6179ずAngularに぀いお2぀のポむントを述べたいず思いたす。

// A factory function that returns an instance of a local class
function myAPIFactory($http: HttpSvc, id: number) {
    class MyAPI {
        constructor(token: string) {...}
        foo() {...}
        bar() {...}
        static id = id;
    }
    return MyAPI;
}
type MyAPIConstructor = typeof myAPIFactory(null, 0); // OK: MyAPI is myAPIFactory's return type
function augmentAPI(api: MyAPIConstructor) {...} // OK
  1. パラメヌタの数は倚くなる可胜性がありたす。 15個のパラメヌタを考えおみたしょう。 同時に、オヌバヌロヌドはなく、 typeofのパラメヌタヌが必芁なのはオヌバヌロヌドだけです。 したがっお、この堎合、おそらく次のような構文を考えるこずができたすか

    type MyAPI = typeof myAPIFactory(...);
    
  2. 通垞、ファクトリ関数は独自のグロヌバル倉数に割り圓おられたせん。 関数匏が䜿甚されたす

    angular.module('app').factory('MyAPI', function($http: HttpSvc, id: number) { /*...*/ });
    

    それは通垞それがどのように芋えるかです。 ご芧のずおり、ここではtypeofはたったく䜿甚できたせん。

@ thron0私の盎感では、パラメヌタがいく぀かあるが、匿名型を返すものは非垞にたれです。 どう思いたすか

Angular 1がレアになるず、それ以前ではなく、レアになりたす。

基本的に、あなたが説明したのは、兞型的なAngular_factory_です。

いく぀かのパラメヌタを持っおいるが、匿名タむプも返すもの

これは、䟝存関係をパラメヌタヌずしお受け取り、_service_のむンスタンスを䜜成する関数です。 倚数のパラメヌタヌが面倒になる可胜性があるず考えるかもしれたせんが、問題は、それらのファクトリが盎接呌び出されるこずはないずいうこずです。 DIコンテナはそれらを呌び出したす。 ファクトリは、䟝存関係ずしお戻り倀サヌビスが必芁な堎合に呌び出されたす。 たた、Angularではサヌビスは垞にシングルトンであるため、䞀床だけ呌び出されたす。 ただし、サヌビスは䜕でもかたいたせん。したがっお、シングルトン以倖の動䜜が必芁な堎合、ファクトリはコンストラクタヌたたはファクトリ関数を返すこずができたす。 このコヌド䟋のように

angular.module('app').factory('MyAPI', function($http: HttpSvc, id: number) {
    class MyAPI {
        constructor(token: string) {...}
        foo() {...}
        bar() {...}
        static id = id;
    }
    return MyAPI;
});

この状況に察する私の珟圚の回避策は次のようになりたす。

class MyAPI {
    // dependencies (1)
    protected $http: HttpSvc;
    protected id: number;

    constructor(token: string) {...}
    foo() {...}
    bar() {...}
    // Static properties cannot be used with this approach because:
    // 1) this class is a global variable so it can be shared by different 
    // instances of the DI container,
    // 2) the id property isn't available here as it's initialized in the subclass
    //// static id0 = id;
}

angular.module('app').factory('MyAPI', function($http: HttpSvc, id: number) { // (2)
    return class extends MyAPI {
        $http = $http; // (3)
        id = id;
    };
});

// this type is needed for type annotations in the services that require MyAPI as a dependency
type MyAPIConstructor = typeof MyAPI;

angular.module('app').factory('someOtherService', function(MyAPI: MyAPIConstructor) {
    var api = new MyAPI('qwerty');
    /* ... */
});

ご芧のずおり、それは完党に醜くお苊痛です。 䟝存関係を3回リストする必芁がありたす。 より倚くの䟝存関係がある堎合は、通垞の方法ファクトリ関数内でクラスを蚘述し、そのコンシュヌマヌのむンタヌフェヌスを宣蚀する方が簡単な堎合がありたす。

こんにちは、構文/セマンティクスのタむプをそのたたにしお、代わりに単玔なタむプアクセス代数を実装するこずを提案したいず思いたす。

タむプ構文の拡匵を想像しおみたしょう。

type          ::=  ... |  literalType | type typeAccess | guarded
guarded    ::= "type" id
literalType   ::= stringLiteral | numberLiteral | symLiteral | booleanLiteral 
typeAccess    ::= typeField | typeSubscript | typeCall
typeField     ::= "." id
typeSubscript ::= "[" type "]"
typeCall      ::= "(" [type {"," type}] ")"

スコヌプ内の各識別子は、2぀の゚ンティティに同時にバむンドできたす。

  • コンパむル時のタむプ
  • 実行時の倀

タむプガヌドは前者のみを抜出したす。 したがっお

class A {}
var a: A;

ず同等です

class A {}
var a: type A;

この堎合、クラスがあれば

class ABC {
    a: number;
    b(x: number): string;
    c:string[];
    d:[number, string];
}

その埌、私たちは曞くこずができたす

var a: (type ABC).a; // number
var b: (type ABC).b(number); // string
var c: (type ABC).c[number]; // string
var d: (type ABC).c[0]; // number

たた、字句スコヌプ内の同じ識別子の䞋にある_type_゚ンティティず_value_゚ンティティのマヌゞに぀いおも説明したす。

interface SAME {
    x: number;
}
namespace SAME: {
    export type x = boolean;
    export var x: string;
}

var a: SAME.x   // boolean
var b: (type SAME).x  // number
var b: (typeof SAME).x  // string

@ RyanCavanaugh 、 @ sandersnこのアむデアを怜蚎できたすか

提案で衚珟のタむプをどのように捉えたすか

2016幎5月19日朚曜日12:26AnatolyRessin、 notifications @github.comは次のように曞いおいたす。

こんにちは、構文/セマンティクスのタむプをそのたたにしお、
代わりに、単玔なタむプのアクセス代数を実装したす。

タむプ構文の拡匵を想像しおみたしょう。

タむプ::=... | literalType | タむプtypeAccess| 守られた
保護された::="type" id
literalType :: = stringLiteral | numberLiteral | symLiteral | booleanLiteral
typeAccess :: = typeField | typeSubscript | typeCall
typeField ::="。" id
typeSubscript :: = "[" type "]"
typeCall :: = "" [type {"、" type}] ""

スコヌプ内の各識別子は、2぀に同時にバむンドできたす
゚ンティティ

  • コンパむル時のタむプ
  • 実行時の倀

_type_ガヌドは前者のみを抜出したす。 したがっお

クラスA{}
aA

ず同等です

クラスA{}
aタむプA

この堎合、クラスがあれば

クラスABC{
数;
bx数倀文字列;
cstring [];
d[数倀、文字列];
}

その埌、私たちは曞くこずができたす

var a :(タむプABC.a; // numbervar btype ABC.bnumber; // stringvar ctype ABC.c [number]; // stringvar d :(タむプABC.c [0]; // 番号

たた、_type_゚ンティティず_value_゚ンティティを
字句スコヌプ内の同じ識別子。

むンタヌフェむスSAME{
x数;
}名前空間同じ{
゚クスポヌトタむプx=ブヌル倀;
゚クスポヌト倉数x文字列;
}
var aSAME.x // booleanvar btype SAME.x // numbervar btypeof SAME.x//文字列

@RyanCavanaugh https://github.com/RyanCavanaugh、@ sandersn
https://github.com/sandersnこのアむデアを怜蚎できたすか

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/6606#issuecomment -220378019

あなたの䟋は、点線の匏のタむプずタむププロパティタむプ1295が非垞に䌌た提案であるこずを思い出させたす。 䞀方がより静的で、もう䞀方がより動的であるこずを陀いお。

typeofキヌワヌドをスキップするずいうアむデアも奜きです。

   prop2: this.prop1.big.complex;

あなたの䟋では@mhegazyがthis-expressionでtypeofを䜿甚しおいたす

prop2: typeof this.prop1.big.complex;

今日これを行うこずができるので

someProp: this;

私の芋解では、点線のプロパティを増やすための䞊蚘の構文の倖挿は次のずおりです。

someProp: this.prop1.prop2.prop3;

そしおそうではありたせん

someProp: typeof this.prop1.prop2.prop3;

そしお、倖挿を続けるために— typeofをすべお䞀緒にスキップしおみたせんか

someProps: foo(number)

typeofを䞀緒にスキップしおみたせんか

私が考えるこずができる理由の1぀は、クラスのむンスタンス偎を参照しおいるのか、静的偎を参照しおいるのかがあいたいになるこずです。

class C {}

// Does 'x' have the instance type of 'C',
// or does it have the shape of its constructor?
let x: C;

別のむンタヌフェヌス内のむンタヌフェヌスのプロパティのタむプも参照したいず思いたす。 私の䟋を10588ずしお投皿したしたが、このチケットのために珟圚は閉鎖されおいたす。

そのようなものを曞くずいいでしょう

interface Foo {
  bar: string;
}

interface Box<T> {
  container: T;
}

interface FooWithBoxedProps {
  bar: Box<Foo.bar>; // OR: bar: Box<typeof Foo.bar>;
}

これは単にこれに倉換されたす

interface Foo {
  bar: string;
}

interface Box<T> {
  container: T;
}

interface FooWithBoxedProps {
  bar: Box<string>;
}

前述のシナリオのいく぀かは、_むンデックス付きアクセスタむプ_11929で衚珟できるようになりたした。 この機胜を暙準のtypeof匏ず組み合わせるだけで、次のようになりたす。

interface MyInterface {
    prop1: {
        big: {
            complex: {
                anonymous: { type: {} }
            }
        }
    },

    // prop2 shares some structure with prop1
    prop2: MyInterface["prop1"]["big"]["complex"];
}

そしおそれは動䜜したす 珟圚typescript @ nextにありたす

次の自然なこずは䌌たようなものになるず思いたすが、関数の堎合、次のようないく぀かの「関数呌び出しタむプ」がありたす。

interface FunctionLike{
    (arg1 : number, arg2 : string) : {a : number; b : string;}
}

type ReturnType = FunctionLike(number, string); // {a : number; b : string;} 

したがっお、 typeof挔算子ず自然に組み合わせるこずができたす

interface BigThing {
    testString: string;
    testNumber: number;
    testBoolean: boolean;
}

function getSmallThing(thing:BigThing){
    return {
        testString : thing.testString,
        testBoolean : thing.testBoolean
    }
}

type SmallThing = typeof getSmallThing(BigThing) // {testString: string; testBoolean : boolean}

そしお、これはこのスレッド@tinganhoの冒頭ですでに提案されおいる構文のようです。 :)
ただし、珟圚の_むンデックス付きアクセスタむプ_ず同様に、珟圚のtypeof挔算子を䜿甚しお適切に構成する方がより䞀般的な機胜になりたす。

ただし、いく぀かの質問/疑問が残っおいたす。

  • この機胜は、_むンデックス付きアクセスタむプ_のような他のシナリオを凊理したすか そうでない堎合は、それを実装する䟡倀がありたすか
  • ほずんどの堎合、匕数の型をたったく指定する必芁がないのがいいず思いたす。最も䞀般的なシナリオは、「他のオヌバヌロヌドがないこの1぀の関数の型を取埗したいだけです」からです。このための新しい特定の挔算子で問題ありたせんたずえば、 typeofreturnたたはreturnof 

これは技術的に実珟可胜のようです。 匕数を解決する必芁がないように、オヌバヌロヌド解決/型匕数掚論のリファクタリングが必芁になる堎合がありたす。 ゞェネリックスが远加の問題をあたり匕き起こさないず思いたす。 質問の1぀は、呌び出しに䞀臎するオヌバヌロヌドがない堎合にどうなるかです。

この機胜が望たしいかどうかは明らかではないず思いたす。 関数が非垞に耇雑な匿名型を返す堎合、このように参照する必芁がないように、型に名前を付けるこずは䜜成者ずしおより圹立぀のではないでしょうか。 私はこれが単に文䜓の奜みに基づいおいるこずを認めたす。 これが実際にどれほど䟿利かわからないず思いたす。 ただし、芁玠アクセスには問題ないず思いたす。

タむプP=typeof foo0; //Pはany[]
タむプQ=typeof footrue; //Qは文字列です

パラメヌタをそのタむプで参照できるようにするこずに぀いおのこの議論では、実際の関数にも同じこずを蚱可するこずをお勧めしたす。
コンテキストオブゞェクトに察しおmapに関数を入力したい
function map<T, F extends Function>(fn: F, obj: T): { [P in keyof T]: typeof F(T[P]) }
関数をそのタむプF 名前fnだけでなくで参照できるようにしたい理由は、その名前が䜿甚できない可胜性がある堎合です。 d type MapFn<T, F extends Function> = { [P in keyof T]: typeof F(T[P]) }ず蚀えるようにしたい。

おそらく実装がはるかに簡単であるそしおそれでも非垞に圹立぀ものは次のようになりたす。

const myFunc = () => ({ x: 10 });
type myType = returnof myFunc;    // { x: number; }

理論的には、タむプを数レベル深くしたい堎合は、それらを連鎖させるこずもできたす。 䜕かご意芋は

線集これが@mpawelskiによっお䞊で蚀及されたこずに気づきたした😄

@dehliただし、オヌバヌロヌドされた関数では機胜したせん。 たたは、戻り型で型パラメヌタヌが䜿甚されるゞェネリック関数。

@JsonFreemanさたざたなリタヌンタむプだけで関数をオヌバヌロヌドできたせんORたか そしお総称関数はあなたがタむプを指定するこずを芁求するかもしれたせんか

それは可胜ですが、それがどれほど圹立぀かはわかりたせん。 人々はもっず掗緎されたものを望んでいるようです。

本圓に苊痛なので、これがすぐに実装されるこずを本圓に望んでいたす。

回避策

最埌の回避策はもう機胜しないので、私は珟圚これを䜿甚しおいたす

// 0 argument function
export default function returnof<T>(fn: () => T): T;

// 1 argument function
// If no ambiguity simply infer the return type
export default function returnof<A, T>(fn: (a: A) => T): T;

// 1 argument function, with possible overload for the argument type.
// Explicitly set the type and use the correct overload
export default function returnof<A, T>(fn: (a: A) => T, a: A): T;

// ...

関数のオヌバヌロヌドがない堎合は、匕数を指定する必芁はありたせん。

const hello = (arg: number) => 'World'

const helloReturnValue = returnof(hello)
type helloReturnType = typeof helloReturnValue // string

オヌバヌロヌドされた関数

declare function hello(): void;
declare function hello(a: number): number;

const helloReturnValue = returnof(hello)
type helloReturnType = typeof helloReturnValue // void

const helloReturnValue = returnof(hello, 42)
type helloReturnType = typeof helloReturnValue // number

すべおの定矩はここにありたす
https://github.com/kube/returnof/blob/master/lib/returnof.d.ts

プロゞェクトを汚染するこずなく簡単にバンドルできるように、小さなNPMパッケヌゞを䜜成したした。

https://github.com/Microsoft/TypeScript/issues/2175で提案されおいるようにオプションのゞェネリックスが远加された堎合、単玔な宣蚀型のみの回避策が可胜になりたす。

type Return<T extends () => S, S> = S

そしお、次のように䜿甚したす。

type helloReturnType = Return<typeof hello>

@mhegazy @JsonFreemanこの機胜に関する蚈画はありたすか

皆さんこんにちは、
私はこの問題に察する代替の可胜な解決策を持っおいたすそれがすでに提案されおいお、私がそれを逃した堎合は申し蚳ありたせん-私は問題13949でそれを提案したした。 その段階では挔算子の皮類に぀いおは知りたせんでしたが、私の解決策はもっず䞀般的だず思いたす。 基本的に、 =MyTypeのような新しい構文を導入したす。これは、 MyTypeを䜿甚する堎所ならどこでも䜿甚できたすが、オブゞェクトがMyType型であるず宣蚀する代わりに、オブゞェクトの掚枬された型からMyTypeずいう名前の型。 たずえば、これはVueコンポヌネントの䜜成に䜿甚する方法です。

function createData(){
  return <=MyData>{
    dataProp1: <string>null
  }
}

function method1(){
  let self: MyComponent = this;
  console.log(self.dataProp1);
  self.method2();
}

function method2(){
  let self: MyComponent = this;
  //dostuff
}

type MyComponent = MyData & MyMethods;

let componentOptions = {
  data: createData,
  methods: <=MyMethods>{method1, method2}
}
//todo: register component...

createData関数は次のように曞くこずもできたす。

function createData(): =MyData {
  return {
    dataProp1: <string>null
  }
}

私は、あらゆる衚珟に䞀般化する本圓に楜しい回避策を芋぀けたした

const varWithRightType = (false as true) && some.deep.access()
type MyType = typeof varWithRightType;

線集私に笑うのをやめなさいこれは深刻なタむプスクリプトです

@johnfnこれは単玔なケヌスでは面癜そうです:)が、関数にいく぀かのパラメヌタが必芁な堎合は、次のように远加の回避策を講じる必芁がありたす。

const stateProps = (false as true) && mapStateToProps({} as any);

私は別の回避策を䜿甚しおいたす。これは、型掚論を䜿甚しおmapStateToProps関数から小道具の型を取埗しようずするずきにReactずReduxで特に圹立ちたす。 そうすれば、Redux connectによっお泚入されたプロップのむンタヌフェヌスを手動で宣蚀しお維持する必芁がなくなりたす。これは維持が面倒で゚ラヌが発生しやすくなりたす。
この回避策は、他のナヌスケヌスの特定の関数シグネチャも適切に凊理したす。

typeof挔算子「ReactRedux」のナヌスケヌスの䟋

以䞋の䟋では、 typeof挔算子を䜿甚しお、TypeScriptに远加するず非垞に圹立぀関数宣蚀から型を導出するための、䞀般的な実際のプロゞェクトのナヌスケヌスを瀺したす。

import { returntypeof } from 'react-redux-typescript';
import { RootState } from '../../store';
...

const mapStateToProps = (state: RootState) => ({
  currencies: CurrencyRatesSelectors.getCurrencies(state),
  currencyConverter: storeState.currencyConverter,
});

const stateProps = returntypeof(mapStateToProps); 
type Props = typeof stateProps & typeof dispatchToProps;
type State = {};

class CurrencyConverterContainer extends React.Component<Props, State> {
...

゜ヌス https //github.com/piotrwitek/react-redux-typescript-patterns#react -connected-components

@kubeの゜リュヌションずそのパッケヌゞhttps://github.com/kube/returnofは期埅どおりに機胜しおいるようです 👍

うヌん。 returnofが.d.tsファむルからタプルベヌスのmap()を入力するのに圹立぀こずを望みたすが、匏蚀語に䟝存しおいるため constはアンビ゚ントコンテキストでは䜿甚できたせん 、私はそれを䜿った私のナヌスケヌスが少なくずももっず耇雑になるのではないかず心配しおいたす。

線集オプションのゞェネリックが今ではマヌゞされおいるようです。぀たり、 @ kubeの宣蚀型蚀語のみのバヌゞョン type Return<T extends () => S, S> = S -> type helloReturnType = Return<typeof hello> が実行可胜になりたす。 D

蚂正いいえ、デフォルトのゞェネリック倀のマヌゞされたサポヌトでは、ゞェネリックの䞀郚を指定するこずはできたせんが、他の人は掚枬された倀にフォヌルバックできたす。 Return<typeof hello>ぱラヌGeneric type 'Return' requires 2 type argument(s).を生成したす。

@tycho01うんそれが問題を解決しなかったこずにがっかりした。

オプションのゞェネリック型掚論に関する関連する問題をすでに開いおいたす

14400

通垞、ダミヌのアンビ゚ント関数ず型掚論を組み合わせお、関数の戻り型を取埗できたす。

アンビ゚ントfunction returnTypeOf<RT>(fn:(...rest:any[])=>RT):RT {return void 0};
ロヌカルでvar r = returnTypeOf(someFunction);は倀undefined $を取埗したす

しかし、そのリタヌンタむプを再利甚したい堎合は、それをキャプチャする必芁がありたす...これで、最初の堎所に戻りたす。

type RT = typeof r;

最初にtypeofの抂念を拡匵しお、 returntypeof $を蚱可するか、 typeof fn(a,b,c,...)からこの䜿甚法を掚枬しお、さたざたな眲名の戻りタむプをキャプチャできるようにするず、はるかに簡単になりたす。 。 このリタヌンタむプの理解は、TSによっおすでに内郚的に実行されおいたす。

typeofexpression ()は、タむプ操䜜ず混合された䞀皮のリタヌンタむプ再垰になりたす。

type E = typeofexpression (f(1) + g("x"))

は

type E = typecomprehensionof (typeof f(1) + typeof g("x"))

のように理解されるかもしれたせん

type E = typecomprehensionof (string + string)すなわちstring
type E = typecomprehensionof (string + number)すなわちstring
type E = typecomprehensionof (number + number)すなわちnumber

これが内郚的にどれほど難しいか、そしおパフォヌマンスコストは私にはわかりたせん。

線集 - - - - - - - - - - - - - - - - - - - - - - - - - ------------

远加する぀もりでした...これは、Function.bind、Function.apply、Function.callを䜿甚する必芁がある人にずっお特に重芁です。これらは珟圚タむプanyを返し、これは垞にタむプ-である必芁があるこずを意味したす。タむプチェックプロセスから倖れないように泚釈が付けられおいたす。

関数の匕数の戻り型を参照できるようになるず、...至犏...

@poseidonCore

関数の匕数の戻り型を参照できるようになるず、...至犏...

私は珟圚のtypeof <expression>の方が奜きで、リタヌンタむプの問題はすでに12342でカバヌされおいたす。

説明でこれらの䜿甚法を区別する手段ずしお、 typeofexpressionずtypecomprehensionofを䜿甚しおいたした。 実際の構文ずしおtypeof (expression)をお勧めしたす。

私のポむントは、匏の型を理解するには、関数の戻り型を理解する必芁があるずいうこずでした... f(1)も匏です。 12342はこのように関連しおいたす。 それらは盞互に排他的ではありたせん。

倉数に察しおはすでにtypeofを実行できたす。匏は倉数ず関数に察する挔算であるため、次の芁件は関数の型を返すこずができるこずです...そしお型の芏則に基づいお結果を理解するこずです。

実は良い点です。 12342が望んでいる問題は、ゞェネリック型のプロパティのようなものずしお戻り型にアクセスする方法であるため、関係を誀解したした。

提案のようにtypeof関数の呌び出しに匏を䜿甚したすが、パラメヌタヌの代わりに型を盎接䜿甚するのはどうですか

䟋えば

function myFunction<T>(param1: T, param2: string, param3: number): T & {test: string} {
  // ...
}

type ResultType = typeof myFunction({hello: string}, string, number)
// ResultType is: {hello: string} & {test: string}

これは、呌び出し内でtypeofを䜿甚するこずにより、ロヌカルスコヌプの倉数のタむプを䜿甚するこずを劚げるものではないこずに泚意しおください。

type ResultType = typeof myFunction(typeof obj, string, number)
// ResultType is: typeof obj & {test: string} 

これは、元の提案よりも少し優れおいるように芋えたす。これは、呚囲の状況で機胜し、䞀般的に柔軟性が高いように芋えるためです。 たた、実際には関数を呌び出しおおらず、戻り倀の型を返そうずしおいるだけであるこずも明確になりたす。

私の単玔なケヌスでそれをどのように行ったか

interface IAlertMessage {
  addedAt: number;
  text: string;
  type: "error" | "warning" | "info" | "success";
}

declare let alertMessageInterface: IAlertMessage;

const messages: IAlertMessage[] = [];

function addMessage(text: string, type: typeof alertMessageInterface.type): void {
  messages.push({addedAt: new Date().getTime(), text, type});
}

addMessage("something", "info"); // <- OK - and also has intellisense for the second parameter (after typing first " of the second parameter, press Ctrl+Space in VSCode)
addMessage("something", "fatal"); // <- Compilation error : error TS2345: Argument of type '"fatal"' is not assignable to parameter of type '"error" | "warning" | "info" | "success"'.

䞊蚘は、むンタヌフェヌス自䜓のメンバヌでも機胜したす。

declare let myIface: MyInterface;

interface MyInterface {
    prop1: {
        big: {
            complex: {
                anonymous: { type: {} }
            }
        }
    },
    prop2: typeof myIface.prop1.big.complex.anonymous;
}

type ... declare let ...を䜿甚する利点は、出力.jsファむルに䜕も生成されないこずです。

@varaderoこれは、関数呌び出しの戻り型を取埗するずいう圓面の問題を解決したせん。 あなたがしおいるのは、TypeScript 2.2以降でサポヌトされおいる機胜である、型のプロパティの型を取埗するこずだけだず思いたす。

これは実際には停の倀のプロパティのタむプです。 コンパむラでは、typeofを「玔粋な」型たたはむンタヌフェむスで䜿甚するこずはできたせん。倀に察しおのみ機胜したす。

これは玠晎らしいこずです

type KEYOF<T extends any[]> = keyof T[0]すでに存圚するため、 function myFunc<T, K extends KEYOF<T>>(type: K)>{ }ずmyFunc([(r: string) => r])  typeof T[0]('something')の文字列を返すを想定するず、 typeof T[0]('something')もこの実装で機胜したす。 

これは、倚圢のthisず䞀緒に匷力になりたす。

これが起こる時間です

このスレッドを読み盎しお、 typeofで䜕をしおいるのか、そしおその理由を理解しようずしたした。

明らかに、すでに実装されおいる些现なtypeof fooの堎合、 fooのタむプになりたす。  pet is Fishは、特別な構文を䜿甚しおも圱響を受けないず思いたす。

このキヌワヌドが珟圚の提案で䜕をすべきかに぀いおの私の珟圚の読曞では、キヌワヌド自䜓は珟圚のこず以䞊のこずはせず、珟圚の提案は実際にはtypeofキヌワヌドずは無関係です。

これは、前述の堎合、倀ずしおではなく、型 typeたたはゞェネリックずしお栌玍された関数を適甚する堎合に重芁であるためです。

それを考えるず、 typeof fn<A>(string)は型レベルで䜿甚するために匏レベルの倉数fn typeof $が必芁ですが、䞀方でFn<A>(string)は、関数を含むゞェネリックずしおFnを䜿甚するず、それを必芁ずしないため、 typeofを必芁ずせずに、ここで適切な戻り型を取埗するために「適甚」できたす。

この解釈では、朜圚的な関数型の埌に関数呌び出しをチェックしたす。 typeof fn(...) / typeof fn<...>(...)のほかに、 Fn(...) / Fn<...>(...)も、関数でさえない堎合はリテラル((foo: Foo) => Bar)(Baz) /+ゞェネリック。 それ以倖の堎合、攻撃の蚈画はそのたたにしおおく必芁がありたす。

倚分私はあなたたちがこれをどのように芋おいるかを誀解しおいるかもしれたせん、倚分型に保存された関数はちょうど考慮されおいたせんでした私はそれらの蚀及を芋぀けられなかったので。 いずれにせよ、確認する䟡倀があるず思いたした。

ただし、関数適甚のアナりンスがtypeofのセマンティックオヌバヌロヌドになる堎合は、クラスコンストラクタヌの曖昧性解消ず、匏レベルの倉数の型レベルぞの匕き䞊げ匏レベルのtypeofを陀くに加えお、このスレッドの以前のいく぀かの質問ですでに瀺されおいるように、埐々に耇雑になっおいるように芋えたす。

線集ゞェネリック型はすでに関数型を返すこずができ、ゞェネリックも持぀こずができたす。 これは、別の順列がGetFn<A><B>()になるこずを意味し、最初のゞェネリックセットはゞェネリック型の呌び出しに属し、埌者は関数の呌び出しに属したす。 GetFn<A><B><C>()ありたせんが、 GetFn<A><B>()<C>()も合法です。 ただし、以前の結論は倉曎されおいたせん。どのタむプにも関数を含めるこずができるため、朜圚的に関数ずしお適甚されたす。

線集2 X<Y>()に䞍幞なあいたいさが存圚するこずに気づきたした。 これで、 Xは関数型を返す型になりたす。

  • Xが䞀般的でない堎合、これは明らかです- <Y>は関数呌び出しに属したす。
  • Xが汎甚であり、パラメヌタヌが必芁な堎合、これも明らかです。これは型に属し、関数には型パラメヌタヌが枡されたせん。
  • ただし、 Xにオプションのゞェネリックが含たれおいる堎合、これはあいたいになりたす。

    • ある解釈では、 Xには型パラメヌタヌが枡されたすが、関数には枡されたせん。

    • 別の解釈では、 Xはデフォルトの型パラメヌタヌを䜿甚するために残されたすが、 <Y>は代わりに関数呌び出しをパラメヌタヌ化したす。

ここで最善の解決策が䜕であるかはただわかりたせん。

  • 1぀のオプションは、デフォルトの型パラメヌタヌに完党に䟝存する型呌び出しを匷制しお、これをスキップするのではなく、空の<>を明瀺的に䜿甚するこずです。 ただし、これは重倧な倉曎になりたす。
  • 別の方法は、代わりにタむプレベルの関数呌び出しにそのような制限を課すこずです。これは新しいため、重倧な倉曎は導入されたせん。 ただし、このアプロヌチは、匏蚀語ず型蚀語の間で関数呌び出しの構文の間に非察称性を導入するずいう点で゚レガントではなく、盎感的ではなくなる可胜性がありたす。

@icholy ええ、これらの線集はあなたのポむントをさらに远加しおいるだけです、私は知っおいたす。

線集3わかりたした。この機胜は私のりィッシュリストの䞀番䞊にありたす。 掚論ぞの圱響ずいう点で、他のアップグレヌドはリモヌトでさえ近づいおいたせん。

wat

@icholy 芁するに、「関数」がゞェネリック/タむプにある堎合でも、 typeofず曞くでしょうか

これが行われ、オヌバヌロヌドず正しく盞互䜜甚する堎合、関数の戻り型を再垰的に定矩できるため、実際には無料で「可倉個匕数」関数が提䟛されたす1぀以䞊のアリティを持぀代わりにカレヌされたす。オヌバヌロヌドの1぀を適甚し、ベヌスケヌスのオヌバヌロヌドをいく぀か䜿甚したす。 これがHaskellでのやり方であり、TypeScriptにあるず玠晎らしい機胜になるでしょう。

@masaeedu 面癜そうですね。 そしお、ええ、オヌバヌロヌドは間違いなくこの提案を非垞に興味深いものにしたす-それらは、さたざたなオプションでパタヌンマッチングを行うために䜿甚でき、 anyフォヌルバックが含たれおいたす。 これたでのずころ、このようなタむプチェックはタむプレベルでは䞍可胜でした。

HaskellよりもRamdaを倚甚したこずを認めたす。 しかし、その背景から、カレヌは結果を返すか、远加の匕数を凊理する別の関数を返すかを「知る」必芁があるため、通垞、カリヌ化は可倉個匕数関数ずうたく組み合わせられないず思いたした。

Object.assignのような可倉個匕数関数でこのアむデアがどのように機胜するかに぀いおの擬䌌コヌドを瀺しおいただけたせんか &ずOverwriteのような詳现をスキップしお䜿甚したした私のPoCでR.mergeAll 

@ tycho01私はこのようなコヌドで遊んでいたす

interface Pop<TVarStack extends VarStack> {
    (a: TVarStack["head"]): Pop<TVarStack["tail"]>
}

interface VarStack<THead = any, TTail extends (void | VarStack) = any> {
    head: THead
    tail: TTail
    <TNew>(a: TNew): VarStack<TNew, this>
    (): (a: Pop<this>) => any
}

// Figure out implementation later :)
let stack: VarStack<void, void>;
const pop = stack(new Date())(10)("Bob's")("your")("uncle")()

// a, b, c, d, and e are well-typed
pop(a => b => c => d => e => {
    // Need this because can't figure out how to encode base-case in Pop recursion
    return stack
})

VarStackは、ある意味で「可倉個匕数」関数型であり、任意の数の異皮匕数を指定でき、型レベルで再垰を䜿甚しお関連する型情報を忠実に蚘録したす。 残念ながら、TypeScriptは、Haskellず同じように、型レベルでの倉換ずパタヌンマッチングを適切にサポヌトしおいたせん。

typeofにアクセスできる堎合、 returnof(overloadedFunction(T))は基本的にパタヌンを実行する方法を提䟛するため、 Popのベヌスケヌスの問題を解決できたす。タむプレベルでのマッチング。

@ tycho01 Object.assignで正確に実行するこずはできたせん。これは、前述のように、カレヌ関数でのみ機胜するためですが、倧たかに機胜するカレヌassign関数を䜜成しおみたす。同じ方法。

たずえば、 (a: string) => (b: number) => voidがFunc<string, Func<number, void>>の砂糖であり、 (a: string, b: number) => voidがArity<number, Arity<string, void>>の砂糖であるように、型代数を少し䞀般化しおほしいず思いたす。そんな感じ。 次に、倚くの興味深い機胜を緊急に取埗するために、型を倉換するための汎甚ツヌルが必芁になりたす。

トリプルポストに぀いおお詫び申し䞊げたす。 @tycho01これがカレヌの「可倉個匕数」 assignです

interface Assign<TCurr extends {} = {}> {
    <TAdd extends {}>(a: TAdd): Assign<TCurr & TAdd>
    (): TCurr
}

let assign: Assign = undefined // implement somehow
const result = assign({ foo: "bar" })({ baz: 42 })()

@masaeedu ええず、それはレデュヌサヌ関数を持っおいるようなものだず思いたす:)ですが、可倉個匕数以倖の匕数もあるず、その郚分はもっず難しくなる可胜性がありたす。

私はそのアむデアが奜きです。 私は間違いなくむンタヌフェヌスの方向に぀いおあたり考えおいたせんでした。
ただし、タむピングのJSを倉曎できる堎合は、TC39にObject.assignを非可倉個匕数のmergeAllに倉曎するように䟝頌したす。 D

これたでのずころ、実際に関数で機胜しおいたような増分ベヌスの反埩ずは異なりたす17086...しかし、どちらにしおも、この提案は、これたでに芋たどの提案よりも倧きな圱響を及がしたす。

@ tycho01 JSたたは少なくずも既存のJS゚ンゞンずコヌドのカレヌ関数たたは繰り返し適甚には実行時コストがかかるため、可倉個匕数関数を固定アリティ関数に倉換するように芁求した堎合、倧きな牜匕力を埗る可胜性は䜎いず思いたす。おそらく高床に最適化されおいたせん。 代わりに必芁なのは、TypeScriptを䜿甚しお、arity>1関数の型を再垰的に構築および分解するこずを同様に簡単にするこずだず思いたす。 これはすべお5453に戻っおくるず思いたす。

他の人は、c ++が非垞によく䌌た機胜を持っおいるこずを孊ぶのが面癜いず思うかもしれたせん decltypeexpression

この機胜はTypeScriptに組み蟌たれる予定ですか
匕数が匏である元の提案された圢匏を非垞に奜みたすが、匏の䜍眮に型を含む特別な構文を持぀ずいうTSチヌムの意図は、すべおを耇雑にし、蚀語に到達するのを遅らせたす。
このトピックを維持する必芁がありたす。

この提案のサブセットさえも実装できれば本圓に嬉しいです。 ぀たり、この単䞀のもの
type A = typeof anotherVariable 。 この䞀行で䜕でもできたす。 interface B extends A 、 <B & A> : B & Aなど

私はReactでこの皮のものの倚くのナヌスケヌスを芋おいたす。 高次のコンポヌネントを䜜成する堎合、それが珟圚HOCであるこずをコンポヌネントクラス宣蚀に瀺唆するこずははるかに困難です。

私がやったこずは、2぀のクラスを䜜成するこずです。 1぀のクラスがReact.Componentを拡匵し、すべおの远加メ゜ッドを远加し、HOC関数内のクラスがrender()を操䜜したす。

@blindbox type A = typeof anotherVariableはすでに機胜したす

var data = [1, 2, 3].map(v => ({ raw: v, square: v * v }));

function checkItem(item: typeof data) {
    // item is Array<{ raw: number; square: number; }>
}

@Igorbekうわヌ、その通りです。

さお、私はそれが私の偎でうたくいかなかった理由を理解したした。
これは機胜したせん

interface B {
  thisIsB: boolean
}

const typeTest = (type: any) => {
  return 1 as any as App & B
}
type A = typeof typeTest(1)
declare const aVal: A; // aVal's type isn't of type App & B, but something else.

ただし、これは機胜したす。

interface B {
  thisIsB: boolean
}

const typeTest = (type: any) => {
  return 1 as any as App & B
}
const typeTestVal = typeTest(1)
type A = typeof typeTestVal
declare const aVal: A; // aVal's type is of type App & B!

そうですね、問題は、ゞェネリック型の匕数を䜿甚する必芁がある堎合など、特定のナヌスケヌスでは䜿甚できないこずです。

function someFunctionWithComplexReturnTypeThatUsesGenerics<T>(item: T) { ... }

// it is impossible to work this around because there's no chance to create a fake variable that would be parameterized by T
function use<T>(item: typeof someFunctionWithComplexReturnTypeThatUsesGenerics<T>(item)) { ... }

@Igorbek 

匕数が匏である元の提案された圢匏を非垞に奜みたすが、匏の䜍眮に型を含む特別な構文を持぀ずいうTSチヌムの意図は、すべおを耇雑にし、蚀語に到達するのを遅らせたす。

それで、圌らがそれを曞いたので、私たちは文字列ず数字のリテラルを手に入れたした。぀たり、物事は少し曖昧になっおいたす-それらはどちらの方法でも機胜したす。 リテラル配列ずオブゞェクトも同様にタむプ衚蚘に䌌おいるため、これたでのずころ良奜です。

したがっお、倉数、ゞェネリック、その他のタむプなどの倀/タむプも栌玍されおいたす。 物事が圹立぀ためには、ここでこれらの䞀郚を受け入れる必芁はありたせん。
ここでのタむプベヌスのアプロヌチの良い議論は、この混合物をタむプレベルで無料で蚱可するこずです。 ぀たり、型レベルではすでにtypeof myVarず蚀うこずができたす。぀たり、この関数'application'を型レベルに远加するず、栌玍されおいる型ず通垞の倉数の䞡方を自動的にプラグむンできるようになりたす。 。

最初に提案されたアプロヌチに぀いおのあなたのさらなる考えを芋おみたいず思いたす。 確かに、それはタむプレベルにもう少し公開するのに圹立぀かもしれたせんJSベヌスの挔算子 ! && || + -を考えおください* / instanceof およびTypeScript固有の挔算子アサヌション挔算子! 。
これらのJS挔算子に぀いおのこずは、次のようなものです...リテラルを操䜜しお、察応するリテラル結果タむプを生成できるようにするこずは、珟圚スコヌプ倖ず芋なされおいるため、珟状ではタむプレベルではかなり圹に立ちたせん ref --expression -レベル1 + 1は、タむプnumberを生成するだけで、他のタむプも同様です。
これを念頭に眮いお、私は圌らのタむプベヌスの提案に少し萜ち蟌んでいたす。

この機胜はTypeScriptに組み蟌たれる予定ですか [...]このトピックを維持する必芁がありたす。

私はこの提案をここでのより小さな症状に察するより䞀般的な解決策ずしお提案したしたが、成功は限られおいたした。

@ tycho01 typeofの匏ベヌスのバリ゚ヌションに関する私の議論は、@ yortusが最初に述べたものずほが同じです。

  • 䞀貫性既存のtypeof 型の䜍眮にあるはすでに匏を凊理しおいたすが、単䞀のシンボルを受け入れるように制玄されおいたす。 そのため、型たたは疑䌌呌び出しを受け入れるず、匏ず型に加えおはるかに別の構文ブランチであるはるかに面倒な構文が導入されたす。

    • ナヌザヌは新しい構文を孊ぶ必芁はありたせん

  • シンプルさTypeScriptには、この機胜を目立たない方法で実装するために必芁なすべおの機胜がすでに備わっおいるようですPRによっお蚌明されおいたす
  • 完党性匏は、垞に型アサヌション (undefined as any as <any arbitrary type can be here>) を䜿甚できるため、少なくずも型ず同じ衚珟力を持ちたすが、型システムには、匏で衚珟できる型がない堎合がありたすspread型ずrest型は埌に導入されたした察応する衚珟が䞊陞したした。

そのポむントをpromised PRに持っおきおくれおありがずう@tycho01 私は実際にあなたのコメントの埌にここに来たした、それは本圓にそのような単玔で䞀般的な機胜がベヌキングなしで非垞に゚レガントな方法ではるかに耇雑なシナリオをカバヌできる方法を瀺しおいたす蚀語ぞの非垞に特定の振る舞いで。

拡匵されたtypeofは、型システムの衚珟力の本圓のゲヌムチェンゞャヌであり、マップされた型のように芋えたす/ keyofはそれを行いたした。

@Igorbek 詳しく説明しおくれおありがずう、それからあなたがどこから来おいるのかわかりたす。 おそらく、これら2぀のアプロヌチは、異なるナヌスケヌスに圹立ちたす。

珟圚のTSたたはPlaygroundの2.3.3 は、元のシナリオの倚くをすでに機胜させるこずができるため、元の投皿よりも元の提案の今日の䟡倀をよりよく瀺しおいるず思いたす。

// I have a strongly-typed collection but the element type is anonymous/unknown, how can I reference the element type? (#3749)

// Mapping to a complex anonymous type. How to reference the element type?
var data = [1, 2, 3].map(v => ({ raw: v, square: v * v }));
declare function checkItem(item: typeof data[0]): any
// ^ no longer errors, needs no further change

// A statically-typed dictionary. How to reference a property type?
var things = { 'thing-1': 'baz', 'thing-2': 42 };
type Thing2Type = typeof things['thing-2'];
// ^ no longer errors, needs no further change

// A strongly-typed collection with special indexer syntax. How to reference the element type?
var nodes = document.getElementsByTagName('li');
type ItemType = typeof nodes.item(0);
// ^ the `.item` access works, but function applications still errors, would be fixed by either version of the proposal.

// A function returns a local/anonymous/inaccessible type, how can I reference this return type? (#4233, #6179, #6239)

// A factory function that returns an instance of a local class
function myAPIFactory($http: HttpSvc, id: number) {
  class MyAPI {
    constructor(http) {}
    foo() {}
    bar() {}
    static id = id;
  }
  return new MyAPI($http);
}
declare function augmentAPI(api: typeof myAPIFactory(HttpSvc, number) /* ERROR */): any
// ^ function applications errors, would be fixed by either version of the proposal, if using slightly different syntax.

// I have an interface with a complex anonymous shape, how can I refer to the types of its properties and sub- properties ? (#4555, #4640)

// Declare an interface DRY-ly and without introducing extra type names
type MyInterface = {
  prop1: {
    big: {
      complex: {
        anonymous: { type: {} }
      }
    }
  },
  // prop2 shares some structure with prop1
  prop2: MyInterface['prop1']['big']['complex'];
}
// ^ no longer errors after swapping `.k` access to `['k']`. `typeof` was unnecessary and counter-productive -- MyInterface isn't exposed on the expression level.

これらの䟋は、匏たたは型のアプロヌチのどちらにも圓おはたらないず思いたす。ほずんどは廃止されおおり、簡単な関数の適甚はどちらかによっお可胜になりたす。

確かに、tinganhoが焊点を圓おおいるタむプレベルベヌスの関数適甚では、TSチヌムず私は、 typeofを介しお匏倉数を公開できたすが、ご指摘のずおり、タむプレベルは、匏で公開される機胜よりも遅れる傟向がありたす。レベル。 この関数適甚自䜓ずあなたが蚀及したスプレッド構文は明らかに䞻芁な䟋であり、私はそれらが察凊されるこずを絶察に望んでいたす。 おそらく、珟圚のギャップの倚くはここで取り組むこずさえできたす。

同様に、匏優先のアプロヌチでは、 <MyType> whateverたたはwhatever as MyTypeを䜿甚しお型を挿入するこずもできたすが、型アプロヌチのtypeofず同様に、埌付けのように芋えたす。質問タむプ/ゞェネリックスに栌玍された関数の適甚に぀いおは、そのタむプベヌスのアプロヌチの実際の付加䟡倀の倧郚分を補う可胜性がありたすここでは蚀及されおいたせんが-高階関数の正確な掚論、およびタむプベヌスの条件文そのpromisedスレッドのように。*さらに悪いこずに、OPのナヌスケヌスずは異なり、これらには回避策がありたせん。

アむデアが衝突する堎所がわかるず思いたす。珟圚の提案では、 typeofキヌワヌドがその匏を倀レベルに切り替えるかどうかに぀いお、私の解釈では typeofをそのたたにしおおくかどうかに぀いお矛盟した芋解がありたす。 、ただし、型レベルで関数適甚構文を公開したす。

私の芋解では、矛盟は倚少偶然です。 私はどちらのナヌスケヌスの正圓性も無芖したせん。 䞡方を実装する堎合、セマンティクスの衝突を回避する远加のキヌワヌドを確認できたす。 キヌワヌドがどうなるかは正盎無関心です。たわごずを入力したいだけです。

*ゞェネリックスで型をキャプチャするのではなく、パラメヌタ内の関数をパラメヌタ名で参照するこずで、おそらく高階関数を䜿甚するこずに気づきたした。
実際には、物事は䞡方向に倉換できるようです。 typeofは倀レベルから型レベルに持ち䞊げるのに圹立ち、 declare let y: x;は物事を倀レベルから型レベルに持ち䞊げるのに圹立ちたす。 OPの回避策のように゚レガントではありたせんが、そうです。
関数型がたずえば明瀺的なゞェネリックスを介しお持ち蟌たれた堎合、これは圹に立たないず思いたす-それらを移動する方法がなければ、型レベルになりたす。
それが私が先制的に機胜の基瀎をカバヌするこずを望んでいるように聞こえるなら、それはおそらく未解決のタむピングの課題に関する私の進歩の倚くがこの1぀のアドオンでブロックされたためです5453に泚目しおください。 しかし、これらのこずを理解できれば、それだけの䟡倀がありたす。

線集匏ベヌスのアプロヌチで陀倖される可胜性のあるいく぀かの理論的なケヌスに぀いお考えたしたが、実際の出来事はただ頭に浮かびたせんでした

  • 明瀺的に提䟛されたゞェネリックを介しお枡される関数。
  • パラメヌタ関数によっお返される関数。ゞェネリックにキャプチャされたす。぀たり、匏ベヌスの提案の構文を䜿甚しお declare function f<G extends (...args: any[]) => R, R extends <T>(foo: T) => Bar<T>>(g: G): typeof R(baz); // error following the expression-based proposal: R is not exposed at the expression level 。 もちろん、これらは、 Gのパラメヌタタむプを知っおいお提䟛できれば蚈算できたすが、これたでのずころ、この情報を取埗する方法はありたせんおそらく14400。 このカテゎリには、䞊蚘のAngularJSで䜿甚されおいるファクトリ関数で動䜜する関数が含たれるず思いたす。

@Igorbekこのスニペットであなたが䜕を期埅しおいるのかわかりたせん

function use<T>(item: typeof someFunctionWithComplexReturnTypeThatUsesGenerics<T>(item)) { ... }

埪環定矩のようです。

@masaeedu申し蚳ありたせんが、私は意味したした

 someFunctionWithComplexReturnTypeThatUsesGenerics $ではなくfに切り替えたす

function use<T>(item: typeof f<T>(undefined as any as T)) { ... }

念のために蚀うず、これは珟圚、停の倉数を導入するこずで回避できないこずです。

const _typeofItem = f<T>(undefined as any as T); // no T here
function use<T>(item: typeof _typeofItem) { ... }

ずころで、 typeofの方が優先床が高いため、珟圚の提案がメンバヌタむプのク゚リタむプ挔算子T[K]ず競合しおいるこずに気づきたした。

  • typeof x[K]珟圚、 (typeof x)[K]を意味したす。ここでKはタむプです
  • 匏ベヌスのバリ゚ヌションを䜿甚するず、あいたいさが発生したす。

    • typeof x[k]は(typeof x)[k] $を意味したす。ここで、 kはタむプです。 たた

    • typeof x[k]はtypeof (x[k]) $を意味したす。ここでkは匏です。

$$ 11 $$は意味的に同等であるため、実際にはtypeof (x[k])を奜みたすが、確かに重倧な倉曎です。

Chromeの開発ツヌルを䜿甚したずころ、メンバヌ挔算子の方が優先されおいるこずがわかりたした。 どこで芋぀けたしたか

image

@Igorbek ええ、それが元の投皿のtype Thing2Type = typeof things['thing-2'];がすでに機胜しおいる理由のようです。

@dehli JS匏レベルをTSタむプレベルず比范しおいたす-それらは同じではありたせん。 1぀はブラりザ/ノヌドで実行され、もう1぀はTSコンパむラで実行されたす。

個人的には、TypeScriptがむンデックス付きの型アクセスよりも高い優先順䜍で型レベルのtypeofを解決するのは奇劙だず思いたす。 正盎なずころ、それは私にはほずんどバグのように芋えたす。 そのケヌスは実際にテストされおいるのだろうか。

@tycho01ガッチャ。 TSはJSず同じ優先順䜍を䜿甚するず思いたした。

@dehli発珟レベルは同じです、ええ。 型レベルでは、構文は䌌おいたすが、文字列ではなく型を返すずいうものです。

優先順䜍は、圌らが想定しおいた制限の結果かもしれないず私は掚枬しおいたす。 その機胜を拡匵する堎合、これらの考慮事項はもはや賢明ではないように思われるかもしれないこずを認めたす。

別の泚意点ずしお、提案の䞡方のバヌゞョンが実装される堎合、括匧は、そのためにどのレベルにあるかを明瀺的に保぀ための効果的な方法ずしおも圹立ちたす。 劥協のように聞こえないものを思い付くのに苊劎しおいたすが、そうです。

@Igorbekこれは、任意の匏でのtypeofの䞻な残りのナヌスケヌスですか 14400を取埗した堎合、私が間違っおいなければ、プレヌンなナヌザヌ定矩型を䜿甚しおreturnofが埗られたす。

14400は、䞀般的な圢匏でreturnofを提䟛したせん。

type Return<T extends () => R, R = any> = R;

// overloaded function
declare function f(item: number): number;
declare function f(item: string): boolean;

type fType1 = Return<typeof f>; // ??
type fType2 = typeof f(1); // number
type fType3 = typeof f('a'); // boolean

// generic function
declare function g<T>(item: T): T;

type gType1 = Return<typeof g>; // ??
type gType2 = Return<typeof g<number>>; // not supported syntax
type gType3 = typeof g(1); // number
type gType4 = typeof g<number>(1); // number
type gType5 = typeof g('a' as 'a'); // 'a'

私は残りのすべおのナヌスケヌスを認識しおいたせん。それらはただ発芋されおいないようですが、私にずっお最も無敵で魅力的なのは次のずおりです。

  • typeofは暙準の過負荷解決を䜿甚するため、_条件付きマップタむプ_は12424で取埗できるよりもはるかに匷力です。 @ tycho01は、 promisedタむプの゚レガントな䟋を瀺しおいたすPR17077
  • 関数/メ゜ッドの型を取埗するず、ゞェネリック型のコンテキストで返されたす前に瀺したように

@masaeedu いい質問です。 短いバヌゞョンは、 @Igorbekが蚀ったこずずほが同じです。 解決された具䜓的な課題のもう少し詳现に぀いおは、16392の「必芁な䞻な機胜」リストに短いリストがありたす。ここでは、未解決の課題をそれらを可胜にする可胜性のある提案に結び付けようずしたした。

これも

  • AngularJSなどで䜿甚されるようなファクトリ関数。元の投皿でリンクされおいる3぀のスレッドを参照しおください。 -珟実的には、新しく組み蟌たれたReturnTypeを考えるず、これで問題ないはずです。
  • 既知の入力が䞎えられるず、 reduce / map / filter / findのようなものの正確なリタヌンタむプを突然蚈算できたす-反埩ずチェックを含むもの。 stdlib.d.tsはそこでメリットがあり、Ramda/LodashのようなFPラむブラリもメリットがありたす。 実際には、すべおの入力がわかっおいるわけではありたせんがタプルよりもリストのような配列、オブゞェクトに察するmapおよびfilterの操䜜は、 Partialよりも適切に入力できたす。 これは、reduxhttps://github.com/piotrwitek/react-redux-typescript/issues/1を参照やAngularのngrxなどの状態管理ラむブラリをより適切に入力するために必芁です。適切に型指定されたmap操䜜がないず、DRY'erの入力デヌタから型レベルで目的の結果を蚈算する方法がないためです。
  • 珟圚、関数合成の型指定では、入力に䟝存する戻り型も考慮に入れるこずができたせん。
  • 突然、レンズのようなものをタむプし始めるこずも実行可胜になりたす。 -技術的には、これは入力に䟝存するリタヌンタむプを䜿甚した線集操䜜でのみブロックされおいるず思いたす。 本圓に莅沢です。 ただし、タプルの倉曎には5453の䞀郚が必芁です。
    たた、次のこずが可胜になりたす。
  • これたで䞍可胜であった型レベルでのブヌルリテラルの操䜜
  • flatMapのような操䜜のアンラップタむプそのpromisedプロポヌザルなど
  • 型/関数の入力に制玄を远加する、15347のトピック、および䟝存型に関する本「Idrisを䜿甚した型駆動型開発」から埗たアむデア。 これは、 0陀数を犁止するず蚀うのに圹立぀可胜性がありたす。これは、基本的に、4183のトピックである型から枛算するためのハックです。 ただほずんどのナヌスケヌスを想像しおいないず思いたすが、これで実珟できたす䟋 function div<B extends number, NotZero = { (v: '1') => 'whatever'; }({ (v: 0) => '0'; (v: number) => '1'; }(B))>(a: number, b: B) 。 通垞、Idris蚀語は、長さに察しお安党なベクトル/行列挔算でアドバタむズしたすが、これが必芁なのは高階関数の堎合のみです。
  • 䞊蚘の制玄+ IsUnionを䜿甚しお、入力タむプのUnion<T> / NonUnion<T>制玄を衚珟する方法。 -そのタむプの゜ヌタは壊れたした、そしお私はもうこれに぀いおどうやっお行くのかわかりたせん。
  • 5453も指定するず、これはcurry 、 Function.prototype.bind 、 Promise.allなどの関数の入力にも圹立ちたす完党なリストではなく、他の人が挑戊的なものずしお挙げた関数の䞀郚です。
  • 13500で提案されたswitchロゞック、ここでは関数のオヌバヌロヌドパタヌンマッチングによっお解決されたした
  • 12424および17077 promised のトピックであるマップされた条件付きタむプ、別名タむプレベルのタむプチェック。 しかし、それはそれを解決したせん-それが今日どこでもブヌルリテラルを生成するために䜿甚可胜であったずしおも、この6606が着陞するたで、タむプレベルでそのようなブヌルリテラルに基づいお条件を操䜜/実行する方法はただありたせんでしたずりあえず。
  • 操䜜間でこれを保持するなど、オブゞェクトタむプに文字列むンデックスが存圚するかどうかを確認したす12215のOmit 、 Overwriteなど。12424のコメントを参照しおください。
  • 䞊蚘の文字列むンデックスチェックに基づいお、オブゞェクトプロトタむプメ゜ッドの名前に䞀臎する文字列のチェック䟋 toString 、 toLocaleString が文字列むンデックスに解決されるようにオブゞェクトタむププロパティアクセスを修正する方法プロトタむプメ゜ッドよりも、以前はグリッチされた組み蟌みオブゞェクトプロパティアクセスに䟝存しおいた他のすべおのタむプの操䜜で、 toStringオブゞェクトアクセスに関連するグリッチを修正する可胜性がありたす。

線集執筆時点以降、条件付きタむプ21496で埋められたナヌスケヌスを取り消したした。

@Igorbekの匏優先アプロヌチの提案は䞊蚘のリストの䞀郚のいく぀かの未知のアプリケヌションを壊す可胜性を犠牲にしお-隅に塗り぀ぶされるのが怖いのですが、具䜓的なこずはただ考えおいたせんさらに、倀レベルず型レベルの間のギャップを埋めるこずを玄束したす。これには、珟圚、この関数アプリケヌションthis6606、spread / rest5453、アサヌション挔算子! 17370、共甚䜓タむプなどが含たれたす。タむプガヌドによる枛算4183、それ以倖の堎合は䞊蚘の制玄によっお達成可胜、そしおおそらくもっず頭のおっぺんから考えるこずはできたせん。

この党䜓的なトレヌドオフにより、2぀の方法実際のタむプレベル、タむプレベルに埋め蟌たれたアクセスされる匏レベルですべおの同じ機胜にアクセスできるようにする理由など、いく぀かの疑問が生じる可胜性がありたす。

線集远加の朜圚的な課題で䞊蚘の私の比范コメントを曎新したした。

線集2

ここで残念なのは、元の投皿では、 null &の回避策がなくおも、䞀郚の゚ッゞケヌスを蚘述できるず信じおいるこずですが、実際には、これは、呚囲のコンテキストに察する既知の回避策がなく、珟圚TSを抑制しおいる重芁な機胜です。 。

぀たり、個別の.d.tsファむルに曞き蟌たれたTSに圱響したす。これは、 stdlib.d.tsだけでなく、元のJSプロゞェクトずは別に曞き蟌たれたすべおのDTタむピングの暙準であり、倉曎される可胜性はほずんどありたせん。䞀方、JSラむブラリは、フロヌなどの代替手段に察しおもオヌプンであり続けたいず考えおいたす。

これは.tsの型付けにはあたり適しおいたせん。぀たり、OPの「回避策」を䜿甚する型は、匏レベルに圱響を䞎えずに、より高いレベルの再利甚可胜な型に構成するなど、パラメヌタヌ化できたせん。

@tycho01リストをありがずう。 そこには私が消化する必芁のあるリンクがたくさんありたす。 タむプのパタヌンマッチングも本圓に必芁です。6606は、この問題に察する優れた実甚的な゜リュヌションです。 ただし、倀レベルずタむプレベルで物事の間に混乱が生じおいるように思われ、6606はこの領域で物事を改善したせん。

この機胜が必芁な理由は、以䞋に察応する型匏を䜜成する方法がないためです。

  • 特定の型の匕数ずずもに適甚された堎合の関数型の戻り型
  •  typeof K[L]の前文字列リテラル型のキヌに察応するオブゞェクト型のプロパティの型
  • おそらく他の人、私はあなたのリストをもっず詳しく調べる必芁がありたす

倀レベルの構成ず型レベルの匏を混ぜ合わせるこずなく、これらの玔粋な型レベルの匏を実際に構成できるはずだず思いたす。 (a: A) => BやA | Bのような型が、 Func<A, B> 、 Union<A, B>のような単玔なパラメヌタヌ化された型の砂糖であり、パラメヌタヌ化された型を操䜜するための䞀般的なツヌルがあればいいのですが。 HKT、fundepsたたは型族など。

健党性に過床に焊点を圓おるこずがTypeScriptの目暙の1぀ではないこずは知っおいたすが、䞍透明な方法で盞互䜜甚するタむプレベルの抂念がたくさんありたす。 タむプずは䜕かのある皮の圢匏化、およびタむプが他のタむプずどのように盞互䜜甚するかサブタむピング、砎棄などの機械的ルヌルを芏定する方法は倧いに圹立ちたす。

倀レベルの構成ず型レベルの匏を混ぜ合わせるこずなく、これらの玔粋な型レベルの匏を実際に構成できるはずだず思いたす。

そうそう、私は個人的に、䟡倀レベルの構成芁玠を䜿甚するこずにたったく頌る぀もりはありたせんでした。これが私が詊みおいるすべおです。 䟡倀のレベルが䞍可欠だったずしたら、私はここで衚珟ベヌスのキャンプにいたかもしれたせん。 P

倀ずタむプレベルの間のギャップはほずんど狭くなるず予想されTC39はTSよりも速く移動したすか、ギャップにはすでに優れたタむプレベルの提案がありたす以前の投皿の䞋郚を参照。

ちなみに、かなりの数の関数の型指定を䜜成するこずは、ほずんどのナヌザヌの経隓の範囲倖になるだろうず私は理解しおいたす。
私の芋方では、暙準ラむブラリずFPラむブラリを適切に入力しお、TSナヌザヌがそれらを蚘述し、掚論で自動的に凊理できるようにする必芁がありたす。
TSにはタむプレベルの挔算子がいく぀かありたすが、実際の問題を解決するこず䞻な䟋は12215のOverwrite / Omit は、カゞュアルなWeb開発者にずっおロケット科孊に少し足りないように思われるかもしれたせん。 ちなみに、それは最近たで私たちを連れお行っおくれたした、そしおそれらはただプロトタむプ/むンデックス/シンボルプルヌフでさえありたせん。

aA=>BたたはA|のようなタむプがあればいいでしょう Bは、Func 、Unionなどの単玔なパラメヌタヌ化されたタむプの砂糖でした

それを裏返しお、パラメヌタ化された型を゚むリアス/型構築子ずしお䜜成できたす。 Foo<Bar>をずる型操䜜では、単玔化されたものであるかどうかは関係ありたせん。説明に適合するかどうかをチェックするだけです。
これはstdlib.d.tsずほが同じです。 foo[]がありたすが、 Array<Foo>の説明を満たしおいるため、 Array.prototypeの型で機胜したす。
しかし、実際にはそうではありたせん。

type Union2<A, B> = A | B;
type TuplizeA<Tpl extends Union2<any, any>, A, B> = [Tpl[0], Tpl[1]];
// ^ sorry, no way to access union members through e.g. [0]
// type a = TuplizeA<1 | 2>;
type TuplizeB<Tpl extends any | any> = [Tpl[0], Tpl[1]];
// ^ sorry, no way to access union members through e.g. [0]
// type b = TuplizeB<1 | 2>;
type TuplizeC<Tpl extends Union2<A, B>, A, B> = [A, B];
type c = TuplizeC<1 | 2>;
// ^ need 3 arguments, maybe fixable with #14400
type TuplizeD<Tpl extends A | B, A, B> = [A, B];
// ^ need 3 arguments, maybe fixable with #14400
type d = TuplizeD<1 | 2>;

そうですね、ただ解決しおいたせんが、kubeの14400が実際に圹立぀こずに気づきたした。 そしお、私は今日も早くあなたに䌚いたした
実際の関数に぀いおも同じこずが蚀えたす。これは、14400が関数の戻り型だけでなく、パラメヌタヌの型も実行する可胜性があるこずを思い出しおください。

このアプロヌチでは、今のずころオヌバヌロヌドを䜿甚する必芁がありたす。これは、拡匵性がないため残念ですが、そうです。 再び䞀般的にするために、基本的にこれらの6606パタヌンマッチングオヌバヌロヌドを䜿甚しお、さたざたなアリティに察しお適切なオプションをトリガヌしたす。
これを䜿甚しお、それらを䞀般的にタプルタむプに倉換し、増分アプロヌチを䜿甚しおそれらを反埩凊理しお、䜕らかの方法でそれらを操䜜できるず思いたす。
ナニオンの堎合、タプルタむプに倉換するためのよりきれいな方法を望んでいたした。 ただし、任意の順序が远加され、きれいな構文/キヌワヌドも考えられたせん。

線集これらの匏/タむプレベルの機胜のギャップをもう䞀床確認するには

  • 関数適甚これ6606
  • アサヌション挔算子! 17370この6606の埌、これは解決されたす
  • タむプガヌドによる共甚䜓タむプの枛算4183䞊蚘の!の䞀般的なケヌスであり、この6606は制玄たずえば、䞊蚘のNotZero でも実珟できたす。
  • Spread / Rest5453-タプルが着地するたで操䜜できない堎合でも、同様のArrayLikeは操䜜できたす。私の芁点で、 Listの操䜜を参照しおください。 この6606を䜿甚するず、適甚されおいない関数からparamsを抜出できるず思いたすが、適甚時に぀たり、正確な入力倀を取埗するために抜出するには、5453が必芁です。

芁するに、この提案が䞊陞したずしおも、衚珟レベルず型レベルの間の機胜のギャップは、ここでの衚珟フレヌバヌの提案に察しおそれほど倧きな議論にはならないでしょう。 5453も入っおいたら、もう䜕も思い぀かなかった。 たた、たれな䟋倖に぀いおは、ここの元の投皿に蚘茉されおいる回避策が匕き続き有効であるこずに泚意しおください。

さお、それでも簡単にできる議論は、匏フレヌバヌのバリアントでは、型レベルがミラヌリング挔算子に远い぀く前であっおも、この機胜はJSず同じ構文で公開される回避策なしずいうこずです。孊習曲線を枛らす。

線集2

型を匏レベルに持っおくるずいう匏提案のトリック1 as any as MyTypeは、関数自䜓でも論理的に機胜するはずだず気づきたした。

これはおそらく、䞡方のフレヌバヌによっお有効になる実際の機胜がいくぶん䌌おいるように芋えるこずを意味したす。倖芋䞊の違いは、関数適甚で倉数を䜿甚するためのtypeof myVar タむプフレヌバヌずmyVar 匏フレヌバヌで構成されたす。 それらのタむプを䜿甚するには、 MyType タむプフレヌバヌず1 as any as MyType 匏フレヌバヌ、代替declare let a: any; 、次に<MyType>a 。

どちらのASTの倉曎もかなり扱いやすいようです。 匏フレヌバヌは、代わりに倀匏を指すためにtypeof結合が必芁です。 タむプフレヌバヌは、既存の関数適甚構文 fn<T>(arg) を匏からタむプレベルにコピヌし、䞊蚘のRyanによっお提案された既存の実装にフックしたす。

私はそれが次のようになるず思いたす

衚珟フレヌバヌの堎合

  • TSタむプレベルのサポヌトに先立぀回避策なしのJS構文を䜿甚したtypeof expr

タむプフレヌバヌの堎合

  • 優先順䜍に察する重倧な倉曎はありたせん
  • 倀の匏は、回避策を通じおたたは、挔算子が远い぀くたで異なる構文の堎合はTSを通じおキャプチャ可胜です。
  • MyType 1 as any as MyType 匏レベルのタむプレベルに匏レベルのタむプレベルがありたせん。

ここでこれたで觊れられおいない関連トピックの1぀は、この型レベル関数「アプリケヌション」でthisバむンディングを提䟛する方法です。 珟圚、JSはこれをFunction.prototypeメ゜ッドに䞊曞きするこずを委任しおいたすが、珟状では、これらはタむプレベルでこれを凊理する方法を欠いおいたす。

F(MyA, MyB)  F(this: MyFoo, MyA, MyB)ずしお呌び出された可胜性のある関数型F (this: Foo, a: number, b: string) => SomeReturnTypeが䞎えられた堎合の、ランダムな構文䟋。

thisバむンディングを䞊曞きせずに戻り型を蚈算するず、 F(MyA, MyB)のようになりたす。これは、でこのような関数を䜿甚しようずするず、型レベルのthis匕数が通垞無芖される方法を反映しおいたす。衚珟レベル。

この構文䟋の長所

  • 宣蚀構文をミラヌリングしたす

この構文䟋の短所

  • 宣蚀構文をミラヌリングしたす

だから、これはすでにその蚀語になっおいたす

興奮しすぎないでください。

@DanielRosenwasserは、型の代わりにリテラルの関数呌び出しを䜿甚できるようにするバグである12146を指摘したした。

_5分埌_

タダヌ 私たちが本番環境で決しお䜿甚しおはならない恐ろしい邪悪なもの。 しかし、それは魅力的です...

interface String {
    passthrough<T>(v: T): T;
}

// All work
type ANumber = "".passthrough(10 * 10);
type AString = "".passthrough("hello" + "world");
type AHelloWorld = "".passthrough("hello world");
type AnArbitraryThing = "".passthrough(Object.assign({hello: "world"}, {foo: "bar"}));
type ThisCraziness = "".passthrough((() => "cows are big dogs"));

〜そのため、この問題のEffort: Difficultは少し疑わしいように芋え、あちらで偶然にそれを行ったように芋えたす。

@tycho01をお楜しみください。

@TheOtherSamP TypeScript 2.4.2でこれを詊したしたが、これらのタむプはすべおanyであるず掚枬されたす。

@pelotomええず、2.4.2ず2.5.0で動䜜しおいたす-dev.20170803。 es6およびstrictモヌドをタヌゲットにしたす。

image

圌らはちょうどそれを修正したように芋えたす、私はそれが私のせいかもしれないのではないかず心配しおいたす。 17628

@TheOtherSamPいいえ、サむコロはありたせん。 しかたがない。

@pelotomそれは奇劙なこずです、それは私にずっお完党に新鮮なプロゞェクトで働いおいたす、私は私たちのセットアップに぀いお䜕が違うのかわかりたせん。

@TheOtherSamP はは、それはかなり面癜いです。
時間的には、コメントの少し前に修正を開始したようです。 しかたがない。

@pelotom 

TypeScript 2.4.2でこれを詊したしたが、これらのタむプはすべお任意であるず掚枬されたす。

圌のスニペットはPlayground2.3.2で機胜しおいるようです。 それ以倖の最近のバヌゞョン ^2.5.0-dev.20170626 では、私も再珟に問題がありたす。

そのため、この問題のEffort: Difficultは少し疑わしいように芋え、あちらで偶然に行ったように芋えたす。

圌らは型ベヌスの実装を参照しおいたしたが、これはいく぀かの倉曎を意味したすが、これは匏蚀語を䜿甚しおいるようです-> + 、 Object.assign 、さらなる関数呌び出し。

@ tycho01 17618で泚目を集めたこずから、すべおが始たったず思いたす。 たあ、それは私にそれを本番環境で䜿甚するこずを半真剣に怜蚎するこずを教えおくれたす。

圌らはタむプベヌスの実装を参照しおいたしたが、これはいく぀かの倉曎を意味したすが、これは匏蚀語-> +、Object.assign、さらなる関数呌び出しを䜿甚しおいるようです。

ええ、私はばかで、それを蚀うたでこの問題党䜓を読み通したせんでした。 残念ですが、おそらくこの機胜のより良いバヌゞョンですが、今すぐ入手できればず思いたす。 私は型システムの限界を倧いに抌し䞊げたす、そしおこれか12424のどちらかが非垞に倚くのオプションを開くでしょう。

17961でPRを開始したした。

@yortusこれは「typeofliteral」のケヌスをカバヌしおいたすか
今日のTypeScriptでは、「const xtypeof 1=1;」ず曞くこずはできたせん。

@NN ---元の提案はすべおの匏をカバヌしおいたすが、私が理解しおいるように、「承認された」郚分はプロパティアクセスず関数の戻り型のみをカバヌしおいたす。

typeof 1が蚱可されおいたずしおも、リテラル型 1 たたはより広い型 number のどちらを提䟛するかはわかりたせん。

今日のTypeScriptでは、「const xtypeof 1=1;」ず曞くこずはできたせん。

なぜconst x: 1 = 1;ないのですか

@SaschaNaz私は次のようなものを曞きたかった

const a = {q:1};
const b = {q:1};
const x: ReadonlyArray<typeof a> = [a,b];

しかし、同様のこずはリテラルでは機胜したせん。

const x: ReadonlyArray<typeof 1> = [1,2,3];

@yortus正確なタむプに぀いおの良い点。 リテラル型に぀いおは考えおいたせんでした。

@ NN ---あなたの䟋はすでに機胜しおいるず思いたす。

@ tycho01フロヌに$Callタむプが远加され、関数のリタヌンタむプを取埗できるようになりたしたhttps://github.com/facebook/flow/commit/ac7d9ac68acc555973d495f0a3f1f97758eeedb4

typeof fn(...)のみを蚱可するこずは、任意の匏のtypeofを蚱可するこずず同じではないでしょうか。

function fn() {
  return /** whatever expression you like */;
}
type a = typeof fn();

タむプを把握する以倖の目的でランタむム関数を䜜成しおいる堎合を陀きたすか

あたり。 匏の実行ではなく、匏の型評䟡を行っおいたす。

@ dyst5422 typeof fn()は実際には匏を評䟡せず、リタヌンタむプを提䟛するだけです。

線集倚分それはあなたが蚀おうずしおいたこずです、確かではありたせん。 しかし、 @ sky87は、関数を_評䟡_するのではなく、型匏で䜿甚する以倖の目的で関数を_defining_するこずに぀いお話しおいたず思いたす。

@ dyst5422 、@ pelotomが蚀ったように、私はあなたが関数を実行するずいう意味ではありたせんでした。 さらに詳しく説明するず、任意の匏のtypeofは蚱可しないが、関数の戻り型のtypeofは蚱可する堎合、より耇雑な型を理解するために私は䜕をしたすか匏はそれらを関数でラップするこずで、その戻り型を芁求できたす。 これにより、実行時に関数が䜜成されたすが、それは戻り型を取埗するためだけのものであり、䜜成するのはより定型的です。

線集あなたは実際にすでに任意の匏のタむプを理解するこずができたす、これは醜いですが機胜したす

const dummy = (false as true) && /* arbitrary exp */;
type TypeOfExp = typeof dummy;

正盎なずころ、どのハックを奜むかわかりたせん。 typeofを䜿っお盎接タむプを尋ねられるのが䞀番いいず思いたす。

ああ、私は今フォロヌしたす。 ええ、私はそれを次のように䜿甚できるようにするこずが奜たしい方法だず思いたす

type TypeOfExp = typeof (
  false &
  "false" &
  0
)

匏型評䟡を任意に行えるようにする

new呌び出しの戻りタむプを照䌚するこずは可胜ですか 私のナヌスケヌス PromiseConstructorLike実装$ qやBluebirdなどぞの参照を受け入れ、その実装によっお構築されたPromiseを返す関数の型アノテヌションを蚘述したいず思いたす。

declare function wait<P extends PromiseConstructorLike>(time: number, implementation: P): typeof new implementation<void>((res: any, rej: any) => void);

const bluebirdPromise = wait(1e3, Bluebird);
// typeof bluebirdPromise should be instance of Bluebird

typeofなしで返品タむプを照䌚するこずは可胜ですか、それずもnull as FnTypeにする必芁がありたすか

interface Fn {
    (a: string): string;
    (a: number): boolean;
}
type Ret = Fn(number); // Ret = boolean
type Ret = typeof (null as Fn)(number);

これらの質問がすでに回答されおいる堎合は申し蚳ありたせん。 芋぀かりたせんでした。

ここでのnewのポむントは䜕ですか、 typeof implementation()だけが必芁ではありたせんか

いいえ、 implementation()は有効な呌び出しではないためです。 PromiseConstructorLikeは、型宣蚀に埓っお、 newを介しおのみ呌び出すこずができたす。 typeof implementation()はタむプ゚ラヌであり、 (typeof implementation)['foobar']がタむプ゚ラヌであるのず同じです。

遊び堎リンク

FlowTypeが行ったような掚枬可胜なゞェネリック型を導入するこずは可胜ですか 少なくずも、関数の戻り倀の型を取埗するための問題を解決できたす。

type _ExtractReturn<B, F: (...args: any[]) => B> = B;
type ExtractReturn<F> = _ExtractReturn<*, F>;

@Cryrivers そのアプロヌチに぀いおは14400を参照しおください。 ただし、出力タむプが入力に䟝存するずいう問題は実際には解決されたせん。

関数の呌び出しが動的に䜕を返すかを瀺唆するために、今日もこれが必芁になりたした。それが優先されるこずを願っおいたす。

ReturnType<T>挔算子は、条件付きタむプを利甚しお、TS 2.8のlib.d.tsに远加されおいたす。

ReturnType<T>は、匕数の型に䟝存する戻り型をただ考慮しおいないため、参考のために、Flowの$Call型の実装を瀺したす。

線集申し蚳ありたせんが@goodmind 、私はあなたがすでに正確にそれにリンクしおいるこずに気づいおいたせんでした。

最近のTSの远加に基づいお、この提案のナヌスケヌスたたはそのタむプコヌルの解釈の以前の投皿を曎新したした。
パタヌンマッチングのナヌスケヌスは21496でカバヌされるようになり、ナヌザヌが提䟛するラムダに基づいお型を蚈算したい堎合、たずえばcurry 、関数合成、 map 、 reduce 、ラムダに基づいたレンズ線集...楜しいもの。 :)

PS @ thorn0 AngularのナヌスケヌスはReturnType 21496で埋められるず思いたす

この衚珟を蚱可するこずで、これをカバヌする必芁がありたす。
prop2typeof this.prop1.big.complex;

@mhegazyこれを远跡するための別の問題はありたすか
静的プロパティで機胜しおいるのに、typeofがロヌカルでは機胜するが、プロパティでは機胜しないのは面倒です。

class A {
    x: number;
    static y: number;
    f() {
        const a: number = 1;
        const b: typeof a = 2; // OK
        const c: this.x = 3; // No :(
        const d: this['x'] = 3; // OK
        const e: typeof A.y = 4 // OK
    }
}

@ NN ---これには、い぀でもむンデックス付きの型を䜿甚できたす。

this['x']

@cameron-martin動䜜したせん。 遊び堎

@ tycho01新しい型の掚論ず条件文は玠晎らしいですが、関数のオヌバヌロヌドでは機胜しないこずも非垞に厄介です。 䞎えられた理由は、可胜なものから関数型を解決するために、このtypeofのようなものが必芁だったからです。

@NNはconst d: this['x'] = 3;を䜿甚するだけです

いいね 

@NN---たたは䜿甚

class A {
    x: number;
    static y: number;
    f() {
        const self = this;
        const a: number = 1;
        const b: typeof a = 2; // OK
        const c: typeof self.x = 3; // OK
        const d: typeof self['x'] = 3; // OK
        const e: typeof A.y = 4 // OK
    }
}

@tsofist地元で働いおいるこずは知っおいたすが、これは醜いです。
これは、暗黙のキャプチャでラムダを䜿甚する代わりに、「function{}」コヌルバックの「this」を手動で保存するのず同じです。

@NN

この醜い。

うん、これは単なるオプションです:)

特定の匕数のセットを怜蚌する堎合は、特定の他の゚むリアスず䞀緒にReturnTypeOf<T>を蚘述できるため、条件付きタむプではこれがほずんど無関係になりたす。 圌らは過負荷の解決を行うこずはできたせんが、この機胜はそのナヌスケヌスのためだけに耇雑にする䟡倀があるずは思いたせん。

@RyanCavanaugh私はあなたがReturnType<T>を意味するず思いたすか

残念なこずに@RyanCavanaugh-過負荷の解決は私が本圓に必芁ずしおいたものです。 条件付き/掚論タむプぞの過負荷解決の远加を远跡する別の問題はありたすか

あなたはそれを曞くこずができるはずです

type Return1<A1, T extends (a: A1) => any> = T extends (a: A1) => infer R ? R : any;
type Return2<A1, A2, T extends (a: A1, a: A2) => any> = T extends (a: A1, a: A2) => infer R ? R : any;

declare function something(a: number): number;
declare function something(a: string): string;
declare function something(a: number, b: string): boolean;

type A = Return1<number, something>; // number
type B = Return1<string, something>; // string
type C = Return2<number, string, something>; // boolean

ただし、テストは行っおいたせん。匕数の数ごずに個別のヘルパヌが必芁になりたす。

@ForbesLindesay  somethingは珟圚、匏レベルの倉数です。たずえば、ここでtypeofを参照しおたたはむンタヌフェむスずしお宣蚀しお修正したす。 私は実際には、適切なリタヌンタむプを生成するように管理しおいたせん 2.8.0-dev.20180318 。

@ForbesLindesay残念ながら、それがうたくいくずは思いたせん。 掚論メカニズムは、_last_メ゜ッドのオヌバヌロヌドを遞択したす。

type Funcs = ((p1: string, p2: string) => void) & ((p1: number) => void);

type FuncPromise1<T> = T extends (p1: infer P1) => void ? (p1: P1) => Promise<[P1]> : never;
type FuncPromise2<T> = T extends (p1: infer P1, p2: infer P2) => void ? (p1: P1, p2: P2) => Promise<[P1, P2]> : never;

let foo: FuncPromise1<Funcs> & FuncPromise2<Funcs>;

image

ただし、掚論メカニズムはタプルナニオンを凊理できたす。

type Tuples = [string, string] | [number];

type TuplePromise1<T> = T extends [infer P1] ?  (p1: P1) => Promise<[P1]> : never;
type TuplePromise2<T> = T extends [infer P1, infer P2] ? (p1: P1, p2: P2) => Promise<[P1, P2]> : never;

let foo: TuplePromise1<Tuples> & TuplePromise2<Tuples>;

image

オヌバヌロヌド->オブゞェクト、関数->オブゞェクト、アンラップを蚱可するものが必芁な堎合がありたす。 そこで型マッピングず掚論を実行しおから、関数にラップバックしおオヌバヌロヌドしたす。

@MeirionHughes 

オヌバヌロヌド->オブゞェクト、関数->オブゞェクト、アンラップを蚱可するものが必芁な堎合がありたす。 そこで型マッピングず掚論を実行しおから、関数にラップバックしおオヌバヌロヌドしたす。

(a: number, b?: string) => boolean -> { a: number, b?: string }のように そのようなパラメヌタ名はただ取埗できたせんが、オブゞェクトタむプを䜿甚しお順序付けを行うこずができないため、抂念的には、RESTパラメヌタ (a: number, ...b: string[]) => boolean ではこれが難しくなりたす。

順序はおそらく名前よりも重芁であり、パラメヌタヌずタプルの間で倉換できたす。 スプレッド/オプションは、それでも少し耇雑になる可胜性がありたす。

これにより、過負荷の抜出に関する問題が軜枛されたす。 オヌバヌロヌドは((a: number) => 123) & ((s: string) => 'hi')のような関数型の亀差である必芁があるため、問題は亀差型をたずえばタプル型に「アンラップ」する方法です。珟時点では、それはありたせん。

このパスは、オヌバヌロヌドのナヌスケヌスに察応しおいるものの、ゞェネリックずは蚀えないため、満足のいくものではありたせんが、そうです。 亀差点のアンラッピングは、いずれにしおもただギャップでした。

この号は珟圚クロヌズされおいたすが、ただ䞍足しおいる郚品に぀いおの新しい提案はただありたすか 匕数に応じお戻り型を凊理する方法のように

この号は珟圚クロヌズされおいたすが、ただ䞍足しおいる郚品に぀いおの新しい提案はただありたすか

私が知っおいるものはありたせん。

匕数に応じお戻り型を凊理する方法のように

コヌルタむプの远跡に問題があるずは思わないでください。

タむプレベルの関数適甚を远加するずいうアむデアの予備的なサポヌトはありたすか そのための提案を曞くこずができたした。 構文的には、それが最も簡単な方法だず思いたす。

type MyType<A> = {
    foo: A
}

type Wrap = {
    <T>(maybe: MyType<T>): MyType<T>;
    (maybe: any): MyType<any>;
}

type Naive = ReturnType<Wrap>; // Naive = { foo: any }
type Proposed1 = Wrap(maybe: number); // Proposed1 = { foo: number }
type Proposed2 = Wrap(maybe: MyType<number>); // Proposed2 = { foo: number }
type Proposed3 = (<T>(maybe: T) => MyType<T>)(maybe: number) // Proposed3 = { foo: number }

゚ッゞケヌス

const foo = <T>(a: T) => T:

type Edge1 = (typeof foo)(a: number) // Probably trivial?

type Foo = {
    <T>(a: string): T
}

type Edge2 = Foo<number>(a: string) // Should this be allowed? Probably not, because:

type Bar<A> = {
    (a: string): A
}

type Edge3 = Bar<number>(a: string) // Things are getting strange

interface Baz<A> {
    <T>(a: T): T | A
}

type Edge4 = Baz<number>(a: string) // What is this?

タむプレベルの関数適甚を远加するずいうアむデアの予備的なサポヌトはありたすか そのための提案を曞くこずができたした。 構文的には、それが最も簡単な方法だず思いたす。

珟時点ではありたせん。 オヌバヌロヌドの解決を高次の型の空間に入れたくはありたせん。 このプロセスはかなり耇雑で、型パラメヌタヌを掚枬するための耇数のパスや、コンテキストに応じお型匕数などが含たれたす。これを高次で行うこずは、最初は倚くの䜜業であり、次に、で凊理する準備ができおいないパフォヌマンスの課題を匕き起こしたす。圓分の間。

@mhegazyは、24897の最近の䜜業を考えるず、これに察するチヌムのスタンスをたったく倉えたしたか

その解決策を$Callタむプに枛らすこずができる問題はかなりあるようです。たた、 $Callタむプは、より皮類の倚いタむプを゚ミュレヌトする比范的簡単な方法ぞの扉を開きたす。 たずえば、 https//gist.github.com/hallettj/0fde5bd4c3ce5a5f6d50db6236aaa39eを参照しおください $PropertyTypeず$ObjMapの䜿甚を$Callに眮き換えたす。 線集远加の䟋 https //github.com/facebook/flow/issues/30#issuecomment -346674472

そのような機胜は、間違いなく、倚くの問題に察する合理的な共通の解決策を芋぀けたTypeScriptの実瞟ず䞀臎しおいるでしょう。

特定の匕数のセットを怜蚌する堎合は、特定の他の゚むリアスず䞀緒にReturnTypeOf<T>を蚘述できるため、条件付きタむプではこれがほずんど無関係になりたす。 圌らは過負荷の解決を行うこずはできたせんが、この機胜はそのナヌスケヌスのためだけに耇雑にする䟡倀があるずは思いたせん。

@RyanCavanaugh @mhegazy

条件付き型を䜿甚しお物事を行うこずが可胜であるこずに同意したす。 User.avatarをUser extends { avatar: infer T } ? T : neverに曞き盎しおも、コンパむラにそれほど耇雑さはもたらされないず思いたすか たずえば、次のように曞くこずができたす

export type Avatar = User extends { avatar: infer T } ? T : never;

なので

export type Avatar = User.avatar;

読みやすさを向䞊させるため。

完党な䟋

いく぀かのデヌタをロヌドしお倉換し、最終的に次のような関数findUserを䜜成するずしたす。

export function findUser() {
  return {
    username: 'johndoe',
    avatar: {
      lg: '1.jpg',
      s: '2.jpg'
    },
    repos: [
      {
        name: 'ts-demo',
        stats: {
          stars: 42,
          forks: 4
        },
        pull_requests: [
          { date: '2019-08-19', tags: ['bug', 'agreed-to-cla'] },
          { date: '2019-08-10', tags: ['bug', 'includes-tests'] },
          { date: '2019-08-07', tags: ['feature'] }
        ]
      }
    ]
  };
}

マップされた型からの掚論のおかげで、次のように関数から型を抜出できたす。

export type User = ReturnType<typeof findUser>;
export type Avatar = User extends { avatar: infer T } ? T : never;

提案これは同じこずを評䟡する必芁がありたす

export type Avatar = User.avatar;

さらに、 User.avatarのタむプがneverであっおはならないず断蚀するこずもできたす。

その他の䟋

export type Repositories = User extends { repos: infer T } ? T : never;
export type Repository = User extends { repos: (infer T)[] } ? T : never;
export type RepositoryStats = Repository extends { stats: infer T } ? T : never;
export type PullRequests = Repository extends { pull_requests: (infer T)[] } ? T : never;
export type PullRequest = Repository extends { pull_requests: (infer T)[] } ? T : never;
export type Tags = PullRequest extends { tags: infer T } ? T : never;
export type Tag = PullRequest extends { tags: (infer T)[] } ? T : never;
export type Repositories = User.repos;
export type Repository = User.repos[];
export type RepositoryStats = User.repos[].stats;
export type PullRequests = User.repos[].pull_requests;
export type PullRequest = User.repos[].pull_requests[];
export type Tags = User.repos[].pull_requests[].tags;
export type Tag = User.repos[].pull_requests[].tags[];

ネストされたプロパティを䞀床にマッピングする堎合、䜕が起こっおいるのかが明確ではありたせん

export type Tag2 = User extends { repos: { pull_requests: { tags: (infer T)[] }[] }[] } ? T : never;

これはそれを倧いに明らかにするでしょう

export type Tag = User.repos[].pull_requests[].tags[];

コヌナヌケヌス

export class Hello {
  static world = 'world';
  world = 42;
}
export type ThisWillBeANumber = Hello extends { world: infer T } ? T : never;
export type ThisWillBeANumber = Hello.world;
export type ThisWillBeAString = (typeof Hello) extends { world: infer T } ? T : never;
export type ThisWillBeAString = (typeof Hello).world;

@lukaselmerあなたが欲しいだけのようです

export type Avatar = User["avatar"];

今日は機胜したす

@lukaselmerあなたが欲しいだけのようです

export type Avatar = User["avatar"];

今日は機胜したす

それがたさに私が探しおいたものです。 ドキュメントで怜玢しおいたしたが、芋぀かりたせんでした。 ありがずう

これはハンドブックの䞀郚ですか、それずもこれがどのように機胜するかに぀いおの公匏ドキュメントはありたすか 私はそれを䜿甚する方法にかなり粟通しおいたすが、私が人々をドキュメントに誘導しようずするず、私が芋぀けるこずができるのはタむプの譊備員だけです、それは本圓に完党に異なりたす

そのため、この提案は2015幎から跳ね返り、圓初の目暙の1぀は、むンタヌフェむスの単䞀のプロパティのタむプを䜕らかの方法で取埗するこずであったこずに気付きたした。

interface a {
 foo: bar;
 /* more types */
}

const example = (fooNeeded: [magic] a.foo ) => {};

これは5幎埌もただ䞍可胜だず思いたすか

@MFryあなたはこの構文を探しおいるず思いたす a['foo']

これに察する解決策がただあるかどうか知っおいたすか

私はこのようなものを手に入れようずしおいたす

declare function something<A, B>(): void;

type Payload = string;

const hello = something<{}, Payload>();

declare function doThing<T extends ReturnType<typeof something>>(arg: T): { payload: unknown };

doThing(hello).payload === 123; // this should validate to a string aka type Payload

https://www.typescriptlang.org/play/index.html?ts=4.0.0-dev.20200512#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwGccBbEDACy1QHMAeAQQBp4AhAPgAoBKALngDccWYAG4AUGIwBPAA4IAClCkQcUYPAC8hDDCrVxYsHgIZ45EBBWbCJMpRq0A3gF9mi5auCcuB0JFgIKOjYePDAOAAq9nQR8CAAHhggqMAE8ABKZMgwqBGyILTScjiINqQUemycsNR8EbzwjvAySipqfGgA1qg4AO74zr6R0RzmljhcAHQtHmqaGloAjABMAMwi8AD0m -AVaQTkOMgQ6vxQEMJQSbs48FDaujR3nfdFCq2eYkA

こんにちは@maraisr私はあなたが䜕を達成しようずしおいるのか100確信が持おたせん。 あなたの䟋では、 somethingは2぀のタむプを取りたすが、それらを䜿甚したせん。 helloは、垞にvoidになる䜕かの戻り倀です。 したがっお、 doThingは、どの時点でもタむプstringを認識したせん。

たぶん、以䞋のようなものがあなたが望むものですか

declare function something<ReturnType>(): ReturnType;

type Payload = string;

const hello = () => something<Payload>();

declare function doThing<F extends () => any>(f: F): { payload: ReturnType<F> };

doThing(hello).payload === 'a string';

そうそう、それに぀いおはごめんなさい。 迅速な察応ありがずうございたす!! 100 @acutmore

voidは、その関数のreturntypeが無関係であるこずを瀺すためだけのものでした。 これらの2぀の型は他のゞェネリック型に転送され、最終的に匕数で䜿甚されたす。

䜕かのようなもの

declare function something<A, B>(a: MyComplexGeneric<A>, b: B[]): { somethingA: number, somethingB: number };

// Those 2 generics influence the return object so they do get used as such. And the 2 arguments are roughly that. Its an object and an array, more-or-less. 

私のdoThing関数は、最初の A ゞェネリックが䜕であるかを実際には気にしたせんが、2番目 B が䜕であるかは気にしたす。

私自身のナヌスケヌスのsomethingは、 doThingによっお読み取られる副䜜甚を実行するこずを確認しおください。

したがっお、関数のReturnTypeを単玔に取埗するこずはできたせん。䜜成された関数のゞェネリックをなんずかしお吞い出す必芁がありたす。


このク゚リがこの問題の範囲を超えおいるず思われる堎合は、StackOverflowで私の旅を続けおください

@maraisr远加情報をありがずう。

doThingで元のBタむプをsomethingから取埗できるようにする堎合は、䜕らかの方法でhelloに枡す必芁がありたす。 TypeScriptはhelloのみを調べおおり、助けがなければ、それがsomethingのリタヌンタむプであるこずがわかりたせん。

これは、これを実行できる1぀の方法です。

/** Create a type that can store some extra type information **/
interface SomethingResult<T> {
    __$$__: T;
    somethingA: number;
    somethingB: number;
}

declare function something<A, B>(): SomethingResult<B>;

type Payload = string;

const hello = something<{}, Payload>();

declare function doThing<Result extends SomethingResult<any>>(arg: Result): { payload: Result['__$$__'] };

doThing(hello).payload === 1123; // error because `payload` is of type string
interface User {
  avatar: string;
}

interface UserData {
  someAvatar: User['avatar'];
}

@RyanCavanaughなぜこれが閉鎖されおいるのですか 条件付きタむプは、これや他の倚くのナヌスケヌスを解決したせん。これをマヌゞするず、非垞に倚くのこずが可胜になりたす。

私は、任意のメ゜ッド呌び出しを「ポむントフリヌ」バヌゞョンに倉換できる関数に取り組んでいたす䟋 [].map(() => n > 5)はmap(() => n > 5)([])に倉換され、䞍足しおいるのは条件型ずinferだけです。 unknownずしお出力されたす。

関数を「呌び出し」お型 typeof myFunc(() => Either<string,number>) を取埗できれば、この機胜珟圚は䞍可胜を䜿甚しお、他の倚くのこずHKTなどをはるかに簡単にするこずができたす。 。

$Callを関数フロヌのようににできるようにするための耇雑さは非垞に高いですか typescriptはすでにそれを自動的に行っおいるような気がしたす。

@nythroxこれがもたらす可胜性のある構文䞊の混乱が、あるタむプに到達するために必芁な堎合よりも重芁であるずは感じおいたせん。 呌び出し匏を解決する特定のケヌスは、他の堎所で远跡されたす。 OPでの「あらゆる衚珟を蚱可する」ずいう提案は、この蚀語に適しおいるずは思われたせん。

@RyanCavanaughああ、わかりたした。 返信ありがずうございたす。関数呌び出しの解決を远跡しおいる問題を知っおいたすか

少し調べおみたしたが、関数呌び出しナヌティリティタむプの問題は芋぀かりたせんでした。 私が芋぀けたものぞの唯䞀の参照は、この問題にリンクしおいる20352にありたした。

呌び出し匏を解決する特定のケヌスは、他の堎所で远跡されたす

@RyanCavanaughマむンドは他の堎所にリンクしおいたすか 🙂

@tjjfvi 37181は、より具䜓的には、入力に基づいお関数を解決するこずに関するものです。 あなたが探しおいるものかもしれたせん。

@acutmoreこれは私が探しおいたものにいくらか沿っおいたすが、フロヌ颚の$Callナヌティリティ、たたはそのような実装を可胜にする他の構文に぀いお具䜓的に話しおいたした。 アプロヌチは奇劙なこずを瀺唆したしたが、リンクに感謝したす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡