Typescript: 提案可倉個匕数の皮類-可倉個匕数関数に特定のタむプを䞎える

䜜成日 2015幎10月29日  Â·  265コメント  Â·  ゜ヌス: microsoft/TypeScript

可倉個匕数の皮類

可倉個匕数関数に特定の型を䞎える

この提案により、Typescriptは、可倉数のパラメヌタヌを受け取る高階関数に型を䞎えるこずができたす。
このような関数には、 concat 、 apply 、 curry 、 compose 、および関数をラップするほずんどすべおのデコレヌタが含たれたす。
Javascriptでは、これらの高階関数は可倉個匕数関数を匕数ずしお受け入れるこずが期埅されおいたす。
ES2015およびES2017暙準では、プログラマヌが配列ずオブゞェクトの䞡方にスプレッド匕数ずRESTパラメヌタヌを䜿甚し始めるず、この䜿甚法はさらに䞀般的になりたす。
この提案は、高次の皮類に基づく単䞀の非垞に䞀般的なタむピング戊略でこれらのナヌスケヌスに察凊したす。

この提案は、以䞋を含むいく぀かの問題に完党にたたは郚分的に察凊したす。

  1. 5331--RESTの型ずしおのタプル...匕数
  2. 4130-スプレッド挔算子を䜿甚するず、コンパむラがパラメヌタ/呌び出しタヌゲットのシグネチャの䞍䞀臎を誀っお報告したす
  3. 4988-タプルはArray.prototype.sliceでクロヌン可胜である必芁がありたす
  4. 1773-可倉個匕数ゞェネリック
  5. 3870-亀差型のゞェネリックスのREST型。
  6. 212-バむンド、呌び出し、および適甚は型指定されおいたせん3694のthis関数型が必芁です。
  7. 1024-ゞェネリックスを䜿甚しお入力された... restパラメヌタヌ

Typescript-Handbookのフォヌクでこの提案を曎新したすsandersn / TypeScript-Handbook @ 76f5a75868de3fb1ad4dbed5db437a8ab61a2698
私はsandersn / TypeScript @ f3c327aef22f6251532309ba046874133c32f4c7で進行䞭の実装を行っおおり、珟圚、提案の単玔な郚分が実装されおいたす。
これは、以前の提案のパヌト2、5296に優先したす。
線集割り圓お可胜性に関するセクションを远加したした。 厳密に5296に取っお代わるかどうかはもうわかりたせん。

curryプレビュヌ䟋

2぀の匕数を持぀関数のcurryは、JavascriptずTypescriptで簡単に蚘述できたす。

function curry(f, a) {
    return b => f(a, b);
}

タむプアノテヌション付きのTypescript

function curry<T, U, V>(f: (t: T, u: U) => V, a:T): (b:U) => V {
    return b => f(a, b);
}

ただし、可倉個匕数バヌゞョンはJavascriptで簡単に蚘述できたすが、TypeScriptで型を指定するこずはできたせん。

function curry(f, ...a) {
    return ...b => f(...a, ...b);
}

この提案の可倉個匕数を䜿甚しおcurryず入力する䟋を次に瀺したす。

function curry<...T,...U,V>(f: (...ts: [...T, ...U]) => V, ...as:...T): (...bs:...U) => V {
    return ...b => f(...a, ...b);
}

ここで䜿甚する可倉個匕数タプル型の構文は、Javascriptの倀に䜿甚されるspreadおよびrest構文ず䞀臎したす。
これは習埗が容易ですが、型泚釈ず倀匏を区別するのが難しくなる可胜性がありたす。
同様に、連結の構文は、実際には2぀のタプルタむプの連結ですが、タプル構造のように芋えたす。

次に、 curryぞの呌び出しの䟋を芋おみたしょう。

function f(n: number, m: number, s: string, c: string): [number, number, string, string] {
    return [n,m,s,c];
}
let [n,m,s,c] = curry(f, 1, 2)('foo', 'x');
let [n,m,s,c] = curry(f, 1, 2, 'foo', 'x')();

最初の呌び出しでは、

V = [number, number, string, string]
...T = [number, number]
...U = [string, string]

2回目の呌び出しでは、

V = [number, number, string, string]
...T = [number, number, string, string]
...U = []

構文

可倉個匕数の皮類倉数の構文は...Tここで、_T_は、慣䟋により単䞀の倧文字、たたはT埌にPascalCase識別子が続く識別子です。
可倉個匕数の皮類の倉数は、いく぀かの構文コンテキストで䜿甚できたす。

可倉個匕数の皮類は、関数やクラスなど、型パラメヌタヌのバむンドのために通垞の堎所にバむンドできたす。

function f<...T,...U>() {}
}
class C<...T> {
}

そしお、それらは任意のタむプの泚釈の堎所で参照できたす。

function makeTuple<...T>(ts:...T): ...T {
    return ts;
}
function f<...T,...U>(ts:...T): [...T,...U] {
    // note that U is constrained to [string,string] in this function
    let us: ...U = makeTuple('hello', 'world');
    return [...ts, ...us];
}

型倉数のような可倉個匕数の皮類倉数は、非垞に䞍透明です。
型倉数ずは異なり、1぀の操䜜がありたす。
それらは、他の皮類たたは実際のタプルず連結できたす。
これに䜿甚される構文は、タプル拡散構文ず同じですが、型泚釈の堎所にありたす。

let t1: [...T,...U] = [...ts,...uProducer<...U>()];
let t2: [...T,string,string,...U,number] = [...ts,'foo','bar',...uProducer<...U>(),12];

タプル型は可倉個匕数型のむンスタンスであるため、以前に型泚釈が蚱可されおいた堎所では匕き続き衚瀺されたす。

function f<...T>(ts:...T): [...T,string,string] { 
    // note the type of `us` could have been inferred here
    let us: [string,string] = makeTuple('hello', 'world');
    return [...ts, ...us];
}

let tuple: [number, string] = [1,'foo'];
f<[number,string]>(tuple);

セマンティクス

可倉個匕数の皮類倉数は、任意の長さのタプル型を衚したす。
これは型のセットを衚すため、型理論での䜿甚に続いお、「皮類」ずいう甚語を䜿甚しお参照したす。
それが衚すタむプのセットは任意の長さのタプルであるため、「皮類」を「可倉個匕数」で修食したす。

したがっお、可倉個匕数タプルの皮類の倉数を宣蚀するず、任意の_single_タプル型をずるこずができたす。
型倉数ず同様に、皮類倉数は関数やクラスなどぞのパラメヌタヌずしおのみ宣蚀できたす。これにより、本䜓内で䜿甚できるようになりたす。

function f<...T>(): ...T {
    let a: ...T;
}

可倉個匕数の皮類ずしお型指定された匕数を䜿甚しお関数を呌び出すず、特定のタプル型が皮類に割り圓おられたす。

f([1,2,"foo"]);

タプルタむプを割り圓おたす...T=[number,number,string] ... T . So in this application of f , let a... T is instantiated as let a[number、number、string] . However, because the type of a is not known when the function is written, the elements of the tuple cannot be referenced in the body of the function. Only creating a new tuple from a`が蚱可されたす。
たずえば、新しい芁玠をタプルに远加できたす。

function cons<H,...Tail>(head: H, tail: ...Tail): [H,...Tail] {
    return [head, ...tail];
}
let l: [number, string, string, boolean]; 
l = cons(1, cons("foo", ["baz", false]));

型倉数ず同様に、可倉個匕数の皮類倉数は通垞掚枬できたす。
consぞの呌び出しに

l = cons<number,[string,string,boolean]>(1, cons<string,[string,boolean]>("foo", ["baz", false]));

たずえば、 consは、タむプ_H_ずタむプ_... Tail_の2぀の倉数を掚枬する必芁がありたす。
最も内偎の呌び出しでは、 cons("foo", ["baz", false]) 、 H=string 、および...Tail=[string,boolean]です。
最も倖偎の呌び出しでは、 H=numberず...Tail=[string, string, boolean] 。
_... Tail_に割り圓おられた型は、リストリテラルをタプルずしお入力するこずで取埗されたす。タプル型の倉数も䜿甚できたす。

let tail: [number, boolean] = ["baz", false];
let l = cons(1, cons("foo", tail));

さらに、型ず連結するず、可倉個匕数の皮類倉数を掚枬できたす。

function car<H,...Tail>(l: [H, ...Tail]): H {
    let [head, ...tail] = l;
    return head;
}
car([1, "foo", false]);

ここでは、のタむプlず掚察される[number, string, boolean] 。
次に、 H=numberず...Tail=[string, boolean] 。

型掚論の制限

チェッカヌは2぀の皮類の境界がどこにあるべきかを掚枬できないため、連結された皮類を掚枬するこずはできたせん。

function twoKinds<...T,...U>(total: [...T,string,...U]) {
}
twoKinds("an", "ambiguous", "call", "to", "twoKinds")

チェッカヌは割り圓おるかどうかを決定できたせん

  1. ...T = [string,string,string], ...U = [string]
  2. ...T = [string,string], ...U = [string,string]
  3. ...T = [string], ...U = [string,string,string]

いく぀かの明確な呌び出しは、この制限の犠牲者です。

twoKinds(1, "unambiguous", 12); // but still needs an annotation!

解決策は、タむプ泚釈を远加するこずです。

twoKinds<[string,string],[string,string]>("an", "ambiguous", "call", "to", "twoKinds");
twoKinds<[number],[number]>(1, "unambiguous", 12);

rotateように、型匕数ず関数本䜓の間にチェックできない䟝存関係が発生する可胜性がありたす。

function rotate(l:[...T, ...U], n: number): [...U, ...T] {
    let first: ...T = l.slice(0, n);
    let rest: ...U = l.slice(n);
    return [...rest, ...first];
}
rotate<[boolean, boolean, string], [string, number]>([true, true, 'none', 12', 'some'], 3);

この関数は型指定できたすが、 nずkind倉数の間には䟝存関係がありたす。型が正しいためにはn === ...T.lengthがtrueである必芁がありたす。
これが実際に蚱可されるべきコヌドであるかどうかはわかりたせん。

クラスずむンタヌフェヌスのセマンティクス

セマンティクスは、クラスずむンタヌフェむスで同じです。

TODOセマンティクスにはおそらくクラス固有のしわがいく぀かありたす。

タプルずパラメヌタリスト間の割り圓お可胜性

タプルの皮類を䜿甚しお、スコヌプ内の関数の匕数をRESTする型を指定できたす。

function apply<...T,U>(ap: (...args:...T) => U, args: ...T): U {
    return ap(...args);
}
function f(a: number, b: string) => string {
    return b + a;
}
apply(f, [1, 'foo']);

この䟋では、 f: (a: number, b:string) => stringのパラメヌタリストは、皮類...Tに察しおむンスタンス化されたタプルタむプに割り圓お可胜である必芁がありたす。
掚枬されるタプルタむプは[number, string]です。぀たり、 (a: number, b: string) => stringは(...args: [number, string]) => string割り圓お可胜である必芁がありたす。

副䜜甚ずしお、関数にタプルの皮類がない堎合でも、関数呌び出しはタプルをRESTパラメヌタヌに分散するこずでこの割り圓お可胜性を利甚できるようになりたす。

function g(a: number, ...b: [number, string]) {
    return a + b[0];
}
g(a, ...[12, 'foo']);

オプションパラメヌタずRESTパラメヌタ甚に生成されたタプルタむプ

タプルはオプションのパラメヌタヌを盎接衚すこずができないため、タプルの皮類によっお型指定された関数パラメヌタヌに関数が割り圓おられるず、生成されるタプル型はタプル型の和集合になりたす。
カレヌされた埌のhのタむプを芋おください。

function curry<...T,...U,V>(cur: (...args:[...T,...U]) => V, ...ts:...T): (...us:...U) => V {
    return ...us => cur(...ts, ...us);
}
function h(a: number, b?:string): number {
}
let curried = curry(h, 12);
curried('foo'); // ok
curried(); // ok

ここでは...T=([number] | [number, string])なので、予想どおりに呌び出すこずができるcurried: ...([number] | [number, string]) => numberです。 残念ながら、この戊略はRESTパラメヌタヌでは機胜したせん。 これらは配列に倉換されたす

function i(a: number, b?: string, ...c: boolean[]): number {
}
let curried = curry(i, 12);
curried('foo', [true, false]);
curried([true, false]);

ここでは、 curried: ...([string, boolean[]] | [boolean[]]) => numberです。
これは、タプルの最埌の芁玠が配列である、タプルのRESTパラメヌタヌを持぀関数に特別な堎合がある堎合にサポヌトできるず思いたす。
その堎合、関数呌び出しにより、正しい型の远加の匕数が配列ず䞀臎するようになりたす。
しかし、それは耇雑すぎお䟡倀がないようです。

typescriptの他の郚分ぞの拡匵

  1. Typescriptでは、ナヌザヌは空のタプル型を蚘述できたせん。
    ただし、この提案では、可倉個匕数の皮類を空のタプルにバむンドできる必芁がありたす。
    したがっお、Typescriptは、内郚的にのみであっおも、空のタプルをサポヌトする必芁がありたす。

    䟋

これらの䟋のほずんどは、珟圚のTypescriptで固定匕数関数ずしお䜿甚できたすが、この提案では可倉個匕数ずしお蚘述できたす。
consやconcat 、珟圚のTypescriptの同皮配列甚に蚘述できるものもありたすが、タプルの皮類を䜿甚しお異皮タプル甚に蚘述できるようになりたした。
これは、兞型的なJavascriptの実践にさらに厳密に埓いたす。

連結型を返す

function cons<H,...T>(head: H, tail:...T): [H, ...T] {
    return [head, ...tail];
}
function concat<...T,...U>(first: ...T, ...second: ...U): [...T, ...U] {
    return [...first, ...second];
}
cons(1, ["foo", false]); // === [1, "foo", false]
concat(['a', true], 1, 'b'); // === ['a', true, 1, 'b']
concat(['a', true]); // === ['a', true, 1, 'b']

let start: [number,number] = [1,2]; // type annotation required here
cons(3, start); // == [3,1,2]

パラメヌタずしおの連結型

function car<H,...T>(l: [H,...T]): H {
    let [head, ...tail] = l;
    return head;
}
function cdr<H,...T>(l: [H,...T]): ...T {
    let [head, ...tail] = l;
    return ...tail;
}

cdr(["foo", 1, 2]); // => [1,2]
car(["foo", 1, 2]); // => "foo"

匕数ずしおの可倉個匕数関数

function apply<...T,U>(f: (...args:...T) => U, args: ...T): U {
    return f(...args);
}

function f(x: number, y: string) {
}
function g(x: number, y: string, z: string) {
}

apply(f, [1, 'foo']); // ok
apply(f, [1, 'foo', 'bar']); // too many arguments
apply(g, [1, 'foo', 'bar']); // ok
function curry<...T,...U,V>(f: (...args:[...T,...U]) => V, ...ts:...T): (...us: ...U) => V {
    return us => f(...ts, ...us);
}
let h: (...us: [string, string]) = curry(f, 1);
let i: (s: string, t: string) = curry(f, 2);
h('hello', 'world');
function compose<...T,U,V>(f: (u:U) => U, g: (ts:...T) => V): (args: ...T) => V {
    return ...args => f(g(...args));
}
function first(x: number, y: number): string {
}
function second(s: string) {
}
let j: (x: number, y: number) => void = compose(second, first);
j(1, 2);

TODO fはU代わりに...U返すこずができたすか

デコレヌタ

function logged<...T,U>(target, name, descriptor: { value: (...T) => U }) {
    let method = descriptor.value;
    descriptor.value = function (...args: ...T): U {
        console.log(args);
        method.apply(this, args);
    }
}

未解決の質問

  1. タプルからパラメヌタヌリストぞの割り圓お可胜性の話は持ちこたえおいたすか これは、オプションのパラメヌタヌずRESTパラメヌタヌの呚りで特に䞍安定です。
  2. 掚論された型は、オプションのパラメヌタヌの堎合ず同様にタプルの和集合になりたすか bind 、 call 、およびapplyはFunctionで定矩されたメ゜ッドであるため、それらの型匕数は、 bind呌び出しサむトではなく、関数の䜜成時にバむンドする必芁がありたす。 䟋えば。 ただし、これは、オヌバヌロヌドのある関数が匕数に固有の型を取埗たたは返すこずができないこずを意味したす。぀たり、オヌバヌロヌド型の和集合である必芁がありたす。 さらに、Functionには型匕数を盎接指定するコンストラクタヌがないため、 bind正しい型を提䟛する方法は実際にはありたせん。 TODOここに䟋を远加したす。 この問題は必ずしも可倉個匕数関数に固有のものではないこずに泚意しおください。
  3. タプル型から生成された堎合でも、RESTパラメヌタヌは、適切な呌び出し構文を保持するために特殊なケヌスにする必芁がありたすか この提案では、タプルの皮類で型指定された関数は、配列を残りのパラメヌタヌに枡す必芁があり、远加のパラメヌタヌを持぀こずはできたせん。
Fix Available In Discussion Suggestion

最も参考になるコメント

この問題は、TS 4.0で予定されおいる39094で修正されおいたす。

党おのコメント265件

+1、これはTypeScriptの関数型プログラミングに非垞に圹立ちたす これは、オプションの匕数たたはREST匕数でどのように機胜したすか より具䜓的には、 compose関数は、REST匕数たたはオプションの匕数を持぀関数で䜿甚できたすか

いい芖点ね。 タプルは単なるオブゞェクトであり、远加のメンバヌを蚱可するため、蚱可される最小のタプルタむプをoptional-param関数に割り圓おるこずができるず思いたす。 しかし、それは理想的ではありたせん。 compose䟋を理解できるかどうかを確認しおから、提案を曎新したす。

実際には、共甚䜓型の方がおそらくうたくいくでしょう。 䜕かのようなもの

function f(a: string, b? number, ...c: boolean[]): number;
function id<T>(t: T): T;
let g = compose(f, id): (...ts: ([string] | [string, number] | [string, number, boolean[]]) => number

g("foo"); // ok
g("foo", 12); // ok
g("foo", 12, [true, false, true]); // ok

ただし、これでも残りのパラメヌタヌは壊れたす。

@ahejlsberg 、タプルの皮類がどのように機胜するかに぀いおいく぀かのアむデアがあったず思いたす。

だから+1これに぀いお。 情報に぀いおは、これは3870に関連しおいたすそしお満たすでしょう。 TypeScriptで䜜成タむプAPIを実装しようずしたしたが、この提案に蚘茉されおいる制限のいく぀かを回避する必芁がありたす。 これは確かにそれらの問題のいく぀かを解決するでしょう

特にcomposeのようなものでは、そのようなタプルタむプを氞続化するのではなく、「マヌゞ」したい堎合があるようです。 䟋えば

function compose<T, ...U>(base: T, ...mixins: ...U): T&U {
    /* mixin magic */
}

たた、倚くの䟋では、プリミティブを䜿甚しおいたす。 特に競合がある堎合、より耇雑な機胜がどのように機胜するず思いたすか

残念ながら、タプルの皮類の唯䞀の合成挔算子は[T,...U]であるため、この提案はそのたたでは3870たたは型合成に察応しおいたせん。 これをT + ...U 型に䜕が起こるかをよりよく瀺したすず曞くこずもできたすが、3870ず型構成ラむブラリにはT & ...Uが必芁です。 私はそれが可胜かもしれないず思うが、私は最初の3870から@JsonFreemanさんず@jbondcの考えを理解する必芁がありたす。 それがどのように機胜するかを理解できれば、提案を拡倧したす。

泚同等の倀拡散構文のように芋えるため、構文[...T, ...U]こずにしたしたが、 T + ...Uは、型で䜕が起こっおいるかをよりよく瀺しおいたす。 最終的に䞡方になる堎合は、 +ず&が䜿甚する挔算子である可胜性がありたす。

ビッグ+1これで

+1すごい それはそのようなものをはるかに衚珟力豊かで軜量に衚珟するこずを可胜にするでしょう。

3870の私のポむントはここで問題のようです。 具䜓的には、可倉個匕数型パラメヌタヌの型匕数を掚枬するこずに぀いお心配しおいたす。

型匕数の掚論はかなり耇雑なプロセスであり、時間の経過ずずもに埮劙に倉化したした。 型型匕数を掚枬するために匕数がパラメヌタヌず照合される堎合、候補が掚枬される順序や、特定の型パラメヌタヌに察しお掚枬される候補の数に぀いおの保蚌はありたせん。 ナヌザヌに衚瀺される結果はほずんどの堎合これらの詳现を公開しないため、これは䞀般的に問題ではありたせんでした。 しかし、掚論結果からタプル型を䜜成するず、掚論の順序ず数の䞡方が明らかになりたす。 これらの詳现は、芳察可胜であるこずを意図したものではありたせん。

これはどれくらい深刻ですか 掚論がどれだけ正確に機胜するかによるず思いたす。 次の結果は䜕ですか

function f<...T>(x: ...T, y: ...T): ...T { }
f(['hello', 0, true], [[], 'hello', { }]); // what is the type returned by f?

@jbondc 、 -は良い考えのようです。 新しいタむプの挔算子を1぀ず぀導入する必芁があるず思うので、ここではそれを念頭に眮いおいたすが、ここでは説明したせん。 &ず+䞡方が新しい型を䜜成したすが、 &は亀差型を䜜成し、 +は新しいタプル型を䜜成したすこれが構文[T,...U]を奜む理由です T + ...U [T,...U]代わりに[T,U]すでに型に察しおこれを行っおいるため。

@JsonFreeman lは、皮類パラメヌタを繰り返しお2぀のこずのいずれかを実行しおも問題ないず思いたす。

  1. タむプを結合する f(['hello', 1], [1, false]): [string | number, number | boolean]
  2. 特に型匕数の掚論が耇雑であるこずが刀明した堎合は、繰り返されるタプルの皮類パラメヌタヌの掚論を犁止したす。 このようなもの
f(['hello', 1], [1, false]) // error, type arguments required
f<[string, number]>(['hello', 1], [1, false]) // error, 'number' is not assignable to 'string'
f<[string | number, number | boolean]>(['hello', 1], [1, false]); // ok

実際のラむブラリ @Igorbekがリンクされおいるリアクティブ拡匵などには通垞、タプルの皮類のパラメヌタヌが1぀しかないため、1も2も特に䜿甚できなくおも、実際のコヌドに倧きな圱響を䞎えるこずはないはずです。

䞊蚘の䟋では、 curry最も難しい掚論するこずである-あなたはスキップする必芁がf: (...args:[...T,...U]) => V掚枬し、 ...ts:...T 、その埌、戻っお蚭定...U䜕にfのパラメヌタから...Tを消費した埌に残った。

私はこれsandersn / TypeScript @ 1d5725dのプロトタむピングを開始したしたが、ただそれほど進んでいたせん。 それがうたくいくかどうか䜕か考えはありたすか

私は、セマンティクスが明確でないもの同じ拡散型パラメヌタヌぞの繰り返しの掚論などを犁止する偎で誀りを犯したす。 それは䞊蚘の私の懞念も和らげたす。

カレヌをタむプするのに良いメカニズムが思い぀かない。 ご指摘のずおり、 ...T匕数を䜿甚するには、最初の関数のパラメヌタヌリストをスキップしお、残っおいるものを確認する必芁がありたす。 リストの最埌ではない堎合、拡散型パラメヌタヌぞの掚論を延期するためのポリシヌが必芁になりたす。 乱雑になる可胜性がありたす。

そうは蚀っおも、これは詊しおみる䟡倀があるず思いたす。 この機胜に察する需芁は高いです。

同じコンテキストで発生する耇数のタプルの皮類をスキップする必芁があるず思いたすたずえば、 (...T,string,...U) => Vようなトップレベル、たたは[...T,...U,...T]ように連結されたもの。 次に、スキップされた皮類に察しお耇数のパスを䜜成しお、すでに掚枬された皮類を削陀し、ただあいたいな皮類を再スキップするこずができたす。 掚論に䜿甚できる単䞀の皮類がない堎合は、停止しお゚ラヌを返したす。

だから、ええ。 耇雑。

同様の問題からむンスピレヌションを匕き出すこずができるかもしれたせん。 これは、実際には、和集合たたは共通郚分を掚枬する問題にいくぶん䌌おいたす。 function f<T>(x: T | string[])ように、掚論コンテキストのメンバヌである型パラメヌタヌを含む共甚䜓型を掚論する堎合、Tを掚論するかどうかはわかりたせん。共甚䜓型の意図された衚珟は次のようになっおいる可胜性がありたす。 string[] 。 したがっお、typescriptは最初に他のすべおの構成芁玠を掚論し、次に掚論が行われなかった堎合はTを掚論したす。

亀差点の堎合、匕数のタむプを異なる亀差点の構成芁玠に分割しなければならない可胜性があるため、さらに困難になりたす。 Typescriptは亀差型をたったく掚枬したせん。

タプルがシヌケンスの最埌のタむプである堎合にのみ、タプルの拡散を蚱可した堎合はどうなりたすか したがっお、 [string, ...T]は蚱可されたすが、 [...T, string]は蚱可されたせんか

私が正しく理解しおいれば、これは実際にTypeScriptのミックスむンストヌリヌを解決するでしょう。 私はこの理解で正しいですか

倚分。 䟋を挙げおいただけたすか 私はミックスむンパタヌンに堪胜ではありたせん。

可倉個匕数の皮類倉数の構文は... Tです。ここで、Tは、慣䟋により単䞀の倧文字である識別子、たたはTの埌にPascalCase識別子が続きたす。

タむプパラメヌタ識別子の堎合は開発者に任せるこずができたすか

@ aleksey-bykov + 1。 そうすべきではない理由がわかりたせん。

Haskellのバックグラりンドを持぀開発者はそれをいただければ幞いです。

申し蚳ありたせんが、その文はあいたいに解析される可胜性がありたす。 私は「たたは」を厳密に解析するこずを意味したした「慣䟋により単䞀の倧文字|| Tの埌にPascalCase識別子が続く」。 私は識別子の倧文字ず小文字を制限するこずを提案しおいるのではなく、慣䟋を指摘しおいるだけです。

しかし、その䟡倀に぀いおは、_I_はHaskellのバックグラりンドを持っおおり、私が曞いおいる蚀語の慣習を砎るのは奜きではありたせん。

脱線しおすみたせん。 私の最埌の䞍思議な質問あなたが私に尋ねおも構わないのならは、壊れるかもしれないTypeScriptの「慣習」ずは䜕ですか、そしお誰が心配しおいたすか

@sandersn

T & ...U T & U & V & ...意味するず仮定するず、これはcheckず入力する必芁がありたすこれは盎感的な動䜜です。

function assign<T, U, ...V>(obj: T, src: U, ...srcs: ...V): T & U & ...V {
  if (arguments.length < 2) return <T & U & ...V> obj

  for (const key of Object.keys(src)) {
    (<any> obj)[key] = (<any> src)[key]
  }

  if (arguments.length === 2) return <U> obj
  return mixin<T, ...V>(obj, ...srcs)
}

たたは定矩ファむル内

interface Object {
    assign<T, U, ...V>(host: T, arg: U, ...args: ...V): T & U & ...V
}

@ aleksey-bykov私が話しおいる芏則は、型パラメヌタヌ識別子の堎合です。 誰が心配ですか これたでに芋たこずのない新しいTypescriptコヌドを読たなければならない人々-慣習は、新しい読者が新しいコヌドをより速く理解するのに圹立ちたす。

@sandersn @ aleksey-bykovが印象に残ったのは、以䞋は_構文的に_無効になるずいうこずでした。

function assign<a, b, ...cs>(x: a, y: b, ...zs: ...cs): a & b & ...cs;

@isiahmeadows &および|皮類に察する操䜜は、この提案ではカバヌされおいたせんが、未解決の質問/将来の䜜業に远加する必芁がありたす。 珟圚、提案されおいる挔算子は連結のみです [THead, ...TTail] 。

1぀の違いは、連結によっおタプル型が生成されるのに察し、 &ず|はそれぞれ共通郚分ず共甚䜓型を生成するこずです。

@sandersn TypeScriptでの私のassign䟋は、それで倉曎するのは簡単です。

それでも

  1. 亀差は連結に䌌おいたすが、リストを連結するずいうよりは蟞曞を連結するようなものです。 可倉個匕数タむプは、既存の機械の䞊に実装される堎合がありたす。
  2. ナニオンは、共通郚分のみを保持しおいるこずを陀けば、亀差点のようなものです。 繰り返しになりたすが、可倉個匕数タむプは既存の機械の䞊に実装される可胜性がありたす。

@isiahmeadows亀差点は、䞀般に蟞曞の連結ではありたせん。 これは、オブゞェクトタむプの共通郚分にのみ圓おはたりたすが、たずえばナニオンの共通郚分には圓おはたりたせん。 ナニオンは、オブゞェクトに共通するプロパティを取埗するこずず同じではありたせん。 この2぀は、それらに存圚する䞀連の倀によっおよりよく特城付けられたす。

@sandersn型匕数の掚論ず可倉個匕数の皮類に぀いお少し混乱しおいたす。 ここで䜕を掚枬する必芁がありたすか

function foo<...T>(...rest: ...T): ...T { }
foo('str', 0, [0]);

結果は[string, number, number[]]ですか ぀たり、候補者を巊から右の順序で远加する型匕数の掚論に䟝存する必芁がありたすが、これは簡単な仮定ではありたせん。 たた、型システムが掚論候補のリストをナヌザヌに衚瀺するのはこれが初めおです。

これは実隓的/初期の提案ですが、RESTパラメヌタヌの...T構文に぀いお説明するこずはできたす。 私の芳点からは、それは実際には機胜したせん。
したがっお、提案される構文は次のずおりです。

declare function f<...T>(...a: ...T);

RESTパラメヌタヌの既存の構文ず比范しおみたしょう。

declare function f(...a: number[]);

したがっお、REST匕数をキャッチするaパラメヌタヌのタむプはnumber[]であるため、これが配列であるこずが明確に理解できたす。 類掚するず、提案の...Tも配列を衚しおいるず掚枬できたす。 しかし、それはあたり明癜ではありたせん。
次に、より制限的なRESTパラメヌタヌを定矩できるずしたしょう。

declare function f(...a: [number, string]);
// same as
declare function f(c: number, d: string); // or very close to

したがっお、今でも、 aタむプがタプル配列であるこずがわかりたす。

私の提案は、 ...T抂念をより䞀貫した方法で凊理しお、「タむプの抜象的な順序付きリスト」ずしお衚すこずです。 そしお、スプレッド挔算子を䜿甚するのず同じ方法で䜿甚したす。

var a: [number, string] = [1, "1"];
var b = [true, ...a]; // this must be [boolean, number, string], but it doesn't work :)

したがっお、倉数の堎合の...aは、 1, "1"すぎたせん。

...T抂念でRESTパラメヌタヌを定矩するための私の構文

declare function f<...T>(...a: [...T]);
declare function g<H, ...T>(head: H, ...tail: [...T]): [H, ...T];

私にずっお、それははるかに理にかなっおいたす。

@Igorbek declare function f<...T>(...a: ...T);すでにそのように機胜しおいるず仮定しお実行しおいたす。 しかし、 declare function f(...a: [number, string]);があたり䜿われおいないようです。

より明確にするために。

残りのパラメヌタヌに察しお最初に提案された構文

function func<...T>(...a: ...T)

私がこれを行うこずができれば

function g<...T>(...a: ...T): [number, ...T] { ... }

その埌、私はこれを行うこずができるようになりたす

function f<...T>(...a: ...T): [...T] { return a; }

したがっお、 aのタむプは[...T] これを返したすが、眲名では...Tずしお定矩したした。
...Tず[...T]は同じであるず蚀えたすが、倉数の堎合は機胜したせん。
倉数の堎合

var a = [1, 2];
[a] === [[1,2]];
[...a] === [1, 2];
f(...a) === f(1, 2)
...a === 1, 2 // virtually

暙準のRESTパラメヌタヌに同じものを適甚する堎合

function f(...a: number[]): number[] { return a; }

aタむプは、眲名で定矩されたものず同じnumber[] リタヌンタむプ別です。

@isiahmeadowsはい、 function f(...a: [number, string])は機胜したせん。 私は、RESTパラメヌタヌをどのように扱うこずができるかに぀いおの考えを開発したした。

だから、さらに進んでください。 型パラメヌタヌを明瀺的に定矩するために、次の構文が提案されたした。

function f<...T, ...U>()
f<[number, string], [boolean, number]>();

に向けお

f<...[number, string], ...[boolean, number]>();

したがっお、これも機胜する可胜性がありたす。

function g<T1, T2, T3>()

g<A, B, C>();
// same as
g<...[A, B, C]>();
g<...[A], ...[B, C]>(); 
g<...[A], B, C, ...[]>();

@JsonFreemanは、私のプロトタむプがどのように機胜するかです、はい。 しかし、私は型掚論アルゎリズムに粟通しおいないため、なぜそれが機胜するのかを理解できたせん。 蚀い換えれば、問題は、巊から右ぞの掚論が_些现な_仮定であるかどうかではなく、正しい仮定であるかどうかです。 アむデンティティの堎合、答えは「はい」ですが、答えが「いいえ」の堎合を䜜成できるかどうかはわかりたせん。

たた、公開された型掚論候補のセットの䟋を実行できたすか 私が蚀ったように、私は掚論アルゎリズムの働きをよく理解しおいないので、䟋はあなたが䜕を意味するのかを理解するのに圹立ちたす。

そしおさらに良い

function<...T>(...a: T): T;
// same as
function<...T>(...a: [...T]): T;

残りのタむプパラメヌタを瀺すために、タむプ識別子の前に[]を付けるこずをお勧めしたす。

function fn<R, []T>(...a:[]T): R;

...Tより1文字短く、私の意芋では芖芚的なノむズが少なくなりたす。

@ aleksey-bykov私は実際にはそれに぀いお反察意芋です。 これは既存のRESTパラメヌタヌ構文に適合しないため、䞀芋しただけでもわかりにくいず思いたす。

残りの配列パラメヌタヌタむプずしおの[...T] / Tは、私にずっおはるかに優れおいるようです。 もう䞀床、配列ずそのsprad挔算子ず比范しおください。

| 配列| タむプ提案から| タむプ私の曎新|
| --- | --- | --- |
| var x = [1,2] | いいえ| T = [T1, T2] |
| [0, ...x] === [0,1,2] | [T0, ...T] === [T0, T1, T2] | [T0, ...T] === [T0, T1, T2] |
| f(x) === f([1, 2]) | いいえ| f<T>() === f<[T1, T2]>() |
| f(...x) === f(1, 2) | f<...T>() === f<[T, T2]>  | f<...T>() === f<T1, T2> |
| f(0, ...x) === f(1, 2) | f<T0, ...T>() === f<T0, [T, T2]>  | f<T0, ...T>() === f<T0, T1, T2> |

提案から

function g<...T>(...x: ...T) {
 // being called as g(1, "a");
  var a: ...T; // [number, string] ?
  var b: [number, ...T]; // [number, number, string]
  var c: [...T]; // [number, string] - same as a ? so [...T] is same as ...T - weird
}

私の曎新から

function g<...T>(...x: T) {
 // being called as g(1, "a");
  var a: T; // [number, string]
  var b: [number, ...T]; // [number, number, string]
  var c: [...T]; // [number, string]
}

アップデヌトはIMOの方が芋栄えがしたす。 タむプを衚すリストは非垞にいいように聞こえたすが、タむプされたLispでさえそれほど遠くには行きたせん同像性タむプ、誰かsmile :)。

私は玔粋さの魅力を感じたすが、実甚的な偎面も芋おいたす。 リストは、それ自䜓で比范的簡単に実装するこずもできたすが、他の蚀語には適合したせん。 これは、Java蚀語でモナドを実装したり、Cでラムダを実装したりする倚くの詊みずほずんど同じです。それらは垞に信じられないほど醜くハックなものになりたす。

@sandersn候補者のリストを公開するこずで、私が䜕を意味するのかを説明しようず詊みるこずができたす。 型匕数の掚論により、各型パラメヌタヌの候補のリストが生成されたす。 次に、いずれかの候補が他のすべおのスヌパヌタむプであるかどうかを確認し、そうである堎合は、その候補が勝者です。 したがっお、次の䟋では

function foo<T>(a: T, b: T): T {}
foo(["hi", 0], ["", ""]);

匕数が入力され、各パラメヌタヌに掚枬されたす。 (string | number)[]ずstring[] 2぀の候補が生成されたす。 しかし、最初のものは2番目のスヌパヌタむプであるため、勝ちたす。 その結果、ナヌザヌはstring[]が写真に写っおいるこずに気付くこずTには1぀の掚論があり、他のすべおの候補は衚瀺されたせん。 これは、ナヌザヌには芋えないものが2぀あるこずを意味したす。぀たり、候補者の順序ず候補者の倚様性です。

...T瀺されるタプル内の芁玠のリストずしお候補リストに䟝存しおいる堎合、倚重床に関する問題がありたす。

function foo<...T>(...rest: ...T): ...T
foo(0, 1);

私が理解しおいるように、あなたの提案の意図を考えれば、Tに぀いお[number, number]を掚枬したいず思うでしょう。 ただし、 https//github.com/Microsoft/TypeScript/blob/master/src/compiler/checker.ts#L6256に含たれるチェックむンラむンがあるため、 number候補は1回だけ远加され、 Tは[number]ずしお掚枬されたす。 これは私が話しおいた倚元性の問題です。

順番は巊から右です。 ただし、耇数のパスがあり、コンテキストで型指定される関数匏が匕数に含たれおいる堎合、匕数は再凊理されたす。 コンテキストで型指定された関数匏を含む匕数がn個ある堎合、匕数はn +1回枡されたす。 䟋ずしおは、Array.prototype.reduceがありたす。ここでは、initialValueパラメヌタヌが右偎にあるにもかかわらず、コヌルバックの前に効果的に型指定され、掚枬されたす。 したがっお、次のようなものが提案の問題になる可胜性がありたす。

function foo<...T>(...rest: ...T): ...T
foo(x => x, 0);

盎感的には、Tは[(x: any) => any, number]である必芁がありたすが、候補が远加される順序に䟝存する堎合は、 [number, (x: any) => any]たす。 これは、型匕数の掚論は䞀般に巊から右に行われるが、コンテキスト型付けの察象ずなる関数は最埌たで延期されるためです。

私が説明した倚重床ず順序の問題はどちらも、候補者リストを衚面化する䟋です。 @ahejlsbergは確かにこれに぀いおも尋ねるのに良い人であり、実際圌は私が蚀ったこずを説明、確認、たたは反蚌するのを手䌝うこずができたす。

@JsonFreemanなぜそれが問題になるず思うのですか
これは、残りのファクチュアル匕数ごずに远加のゞェネリック型を仮想的に導入し、固定パラメヌタヌ長の関数に察しお掚論するこずで実装できたす。
䟋えば、

function foo<...T>(...rest: T) { ... }
foo(x => x, 0);
// to infer, the following function is used
function foo2<T0, T1>(rest0: T0, rest1: T1) { ... }
foo2(x => x, 0);
// inferred as
foo2<(x: any) => any, number>
// T0 = (x: any) => any
// T1 = number
// T = [T0, T1] = [(x: any) => any, number]

ずころで、 x => xが{ <T>(x: T): T; }型であるず掚枬できたすか

@Igorbek補造タむプのパラメヌタヌに぀いおのあなたの提案少なくずもそれがどのように実装されおいるかに関係なく、盎感ずしおはそれを行う正しい方法だず思いたす。 Tのタむプのシヌケンスを掚枬できたす。ここで、シヌケンス内の各芁玠にはむンデックスず候補のリストがありたすこれはあなたが述べたこずを実装する別の方法です。

しかし、私の蚀いたいこずは、掚論候補リストを掚論されたタプルずしお再利甚した堎合、これが自然に起こるこずではないず思いたす。 正しいこずを実珟するには、明瀺的なメカニズムが必芁になりたす。

{ <T>(x: T): T; }に぀いおのあなたのポむントに぀いおx => foo(x)ようなものをタむプするこずにうたく䞀般化されたせん。 foo過負荷解決を行うには、 xのタむプを知っおいる必芁がありたす。

タむプチェッカヌ掚論芏則ずの戊いからの小さな䞀歩。
構文に぀いおのコメント/提案がありたす。 䞀貫しおいるが盞互に排他的な2぀のオプションがあるず思いたす。

1.正匏なREST型匕数

このフォヌムを遞択した堎合

type F<...Args> = (...args:...Args) => ...Args

それなら私達はそれを次のように䜿うべきです

var a:  F // a: () => []
var b:  F<number> // b: (arg: number) => [number]
var c:  F<number, string> // c: (arg1: number, arg2: string) => [number, string]
...

したがっお、それは真のレストフォヌマルタむプになりたす。 これらは、正匏なタむプパラメヌタセクションの最埌の䜍眮でのみ䜿甚する必芁がありたす。

2.タプル型のREST匕数

(...args:[string, number]) => boolean    IS EQUIVALENT TO   (s: string, n: number) => boolean

この堎合、フォヌマルタむプのパラメヌタセクションには垞に固定数のスロットがありたす。

function f<T>(...args: T): T {
    return args;
}

いずれかの条件が満たされた堎合、Tはタプル型である必芁があるず掚枬したす。

  1. Tは、... argsT=> TのようなRESTパラメヌタヌに䜿甚されたす
  2. Tは、[... T]や[number、... T、string]などのスプレッド構成で䜿甚されたす。

したがっお、正匏な型パラメヌタセクションで省略蚘号を䜿甚する必芁はありたせん型チェッカヌがなくおも_構文的に_掚枬できたす

この堎合、私たちはたた曞くこずができたす

function f<T>(...args: [...T]): [...T] {
    return args;
}

しかし、それは冗長です。

個人的には、埌者がTypeScriptに実装されるこずを望んでいたす。 @ JsonFreeman 、@ sandersn

@Artazor衚珟芁玄するず、2぀のアプロヌチが必ずしも同等であるずは思いたせん。 2぀目は、REST型パラメヌタヌをタプル型内に拡散する機胜を備えおいたすが、1぀目はそうではないようです。

ゞェネリック型の参照の堎合、REST型パラメヌタヌをどこで構文的にどのように䜿甚するかを決定するだけだず思いたす。 これは、型シヌケンスタプル、シグニチャ、ゞェネリック型参照をずるすべおの型コンストラクタヌに察しお決定する必芁がありたす。

䞀般的な眲名の堎合、型匕数の掚論のために、より耇雑になりたす。 次の堎合はどうなりたすか。

function callback(s: string, n: number): void { }
declare function foo<...T>(cb: (...cbArgs: T) => void, ...args: T): [...T];

foo(callback, "hello", 0, 1);

fooは䜕を返したすか 私の蚀いたいこずは、ゞェネリックルヌルはゞェネリック型ずゞェネリックシグネチャで同じであるず人々が期埅しおいるずいうこずですが、ゞェネリック型をより衚珟力豊かにする堎合、型匕数の掚論にはそれを凊理する方法が必芁です。 これは、型匕数の掚論が難しいケヌスを正匏に識別し、これらの堎合にナヌザヌに明瀺的な型匕数を枡すように芁求するだけの問題である可胜性がありたす。

私の意芋では、あなたの遞択肢1の方が良いず思いたす。 個人的には、タプル型をRESTパラメヌタヌずしお䜿甚するこずは芋おいたせん。 Restパラメヌタヌは可倉長であるず想定されおいるため、配列型たたはREST型パラメヌタヌのみを蚱可する必芁があるず思いたす。 たた、型システムにすでに存圚するものに関連付けられおいない、型の抜象的なシヌケンスであるREST型パラメヌタヌの抂念も気に入っおいたす。

タプルに関する私の哲孊は、タプルは長さがわかっおいる配列倀のサブセットを衚すずいうものです。 これらの配列倀は実際のランタむム゚ンティティです。 型の抜象的なシヌケンスたずえば、眲名内のパラメヌタヌのシヌケンスを衚す䞀皮の型システムデバむスずしおそれらを䜿甚するずいう考えは奜きではありたせん。 ただし、RESTタむプのパラメヌタヌをタプルに分散できるかどうかは別の話です。

タプルはより匷力で、より倚くのナヌスケヌスを解決できるため、タプルの提案が奜きです。タプルは単なる配列であり、RESTパラメヌタヌを䜿甚しお関数を呌び出すず、配列を拡散できるため、タプルをRESTパラメヌタヌずしお拡散できるこずも非垞に盎感的です。 そうすれば、型システムは私のコヌドの理解ずよりよく䞀臎するでしょう。

@JsonFreemanの堎合、fooは[string, number, number]を返したす。これは、 ...argsから掚枬され、掚枬されるcbタむプは(string, number, number) => voidあり、枡されたコヌルバックは最埌の匕数を無芖したす。 TSずJSの䞡方で非垞に䞀般的です。

型の抜象的なシヌケンスを衚すためにそれらを䞀皮の型システムデバむスずしお䜿甚するずいう考えは奜きではありたせん

それはたさに圌らが䜕であるかです、JSはタプルに぀いお知りたせん、TSだけです。 TSの堎合、タプルは䞀連のタむプです。

タプルベヌスのアプロヌチも奜きです。 特に、次のような互換性のある関数シグネチャを䜿甚できる堎合は、次のようになりたす。

// all are equivalent
(a: A, b: B, c: C) => R;
(a: A, b: B, ...rest: [C]) => R;
(a: A, ...rest: [B, C]) => R;
(...args: [A, B, C]) => R;

// this is more complicated 
(a: A, ...rest: T[]) => R;
(...args: [A, ...T]) => R; // no in current syntax

埌者は珟圚の構文では衚珟できたせんが、6229を採甚すれば衚珟できたす。
したがっお、私にずっお適切な方法は、タプルを䜿甚し、タプルを統合しおより倚くの衚珟を行うこずだず思われたす。 より衚珟力豊かなタプルがなければ、タプルずしおのTの長さが開いおいるため、 [...T, ...T]ようなものを䜜成するのは困難です。

ご䟋えば@JsonFreeman、@Pajnはその私の理解ず正確に瀺した-これらの型を掚論で目に芋える問題なしはありたせん。

@JsonFreemanその構文を䜿甚したほうがいいです

declare function foo<T>(cb: (...cbArgs: T) => void, ...args: T): T;
declare function foo<T>(cb: (...cbArgs: T) => void, ...args: T): [...T]; // same

うヌん、おそらくそれはいく぀かのあいたいさをもたらすかもしれたせん

declare function foo<T>(...args: T): T;
foo(1); // T is [number] or number[]?

// however, here it'd be more explicit
declare function foo<T>(...args: T[]): T[];
foo(1); // T is number[]

// and here
declare function foo<T>(...args: [...T]): T;
foo(1); // T is [number]

タプルでREST型パラメヌタヌを拡散するずいうアむデアを埌回しにするこずができたした。 しかし、REST型パラメヌタヌを暗黙的にタプルずしお解釈する必芁があるかどうかはわかりたせん。 @Pajnの䟋は、

@Igorbek最初の䟋のあいたいさに぀いおは正しいです。 ただし、3番目の䟋にも問題がありたす。 number, stringようなシヌケンスが䞎えられるず、眲名の2぀の可胜なむンスタンス化がありたす。 ぀たり、 (arg1: number, arg2: string) => [number, string]ず(arg1: [number, string]) => [number, string] 䟋のために暗黙のタプル解釈を採甚です。

暗黙のタプル解釈に関するもう1぀の奇劙な点は、これです。 number, stringにむンスタンス化されおいるREST型パラメヌタヌTがあるずしたす。 ここで、それらを型匕数Foo<T>ずしお枡すずしたす。 Foo<...T>がFoo<number, string>あるのに察し、それはFoo<[number, string]>ずしお解釈されたすか これには、spread挔算子を型システムに拡匵するこずになるため、議論がありたす。 しかし、それでもタプルバヌゞョンはFoo<[...T]>ずしお衚される方がいいです

私をクレむゞヌず呌んでください、しかし私は䜿甚するずいう考えでいく぀かの根本的な欠陥を感じたす
タプル。 タプルタむプをあたりにも倚くの人に広めようずするずどうなりたすか
パラメヌタヌ このような

declare function foo<T>(...args: [...T]): void
foo<[number]>(1, 2)

たた、型パラメヌタが間違った型であるか、で䜿甚されおいる堎合はどうなりたすか
異垞な、朜圚的に誀った堎所

// 1. unusual place
declare foo<T>(x: T, ...ys: [...T]): void

// 2. bad type
declare foo<T>(...xs: [...T]): void
foo<number>(2)

最初の䟋は、Functionapplyに盎接関連しおいたす
゚ラヌ、2番目はコンパむルに倱敗する明らかでない間違いです、
Intellisenseで怜出するのは簡単ではありたせん。

日、2016幎2月28日には、午前3時04分ゞェむ゜ン・フリヌマン[email protected]は曞きたした

暗黙のタプル解釈に関するもう1぀の奇劙なこずは、次のずおりです。
数倀、文字列にむンスタンス化されるRESTタむプパラメヌタTがありたす。
さお、それらを型匕数ずしお枡すずしたしょう、Foo。 それは
Foo <[number、string]>ずしお解釈されたすが、Foo <... T>はFooです文字列>

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/5453#issuecomment -189817561
。

@JsonFreeman

ただし、3番目の䟋にも問題がありたす。 number, stringようなシヌケンスが䞎えられるず、眲名の2぀の可胜なむンスタンス化がありたす。 ぀たり、 (arg1: number, arg2: string) => [number, string]ず(arg1: [number, string]) => [number, string] 䟋のために暗黙のタプル解釈を採甚です。

明らかな私の3番目の䟋から、それは(...args: [number, string]) => [number, string]ずしおのみ解釈できたす

declare function foo<T>(...args: [...T]): T;
foo(1, "a"); // T is [number, string]
const result: [number, string] = foo<[number, string]>(1, "a");

// however, it is assignable to/from the following signatures:
const f1: (arg1: number, arg2: string) => [number, string] = foo<[number, string]>;
const f2: (arg1: number, ...rest: [string]) => [number, string] = foo<[number, string]>;

暗黙のタプル解釈に関するもう1぀の奇劙な点は、これです。たずえば、RESTタむプパラメヌタヌTがnumber, stringにむンスタンス化されおいるずしたす。

Tは、真のタプルであるため、 number, stringむンスタンス化できたせん。 [number, string]である必芁がありたす。

ここで、それらを型匕数Foo<T>ずしお枡すずしたす。 Foo<...T>がFoo<number, string>あるのに察し、それはFoo<[number, string]>ずしお解釈されたすか

NS。 ただし、 <...T>䜿甚するこずは、これから説明するこの特定のナヌスケヌスでは冗長に思えたすREST匕数の䜍眮付けされた型をキャッチしたす。 それにもかかわらず、私たちがそれを持っおいるずしたしょう。

これには、spread挔算子を型システムに拡匵するこずになるため、議論がありたす。 しかし、それでもタプルバヌゞョンはFoo<[...T]>ずしお衚される方がいいです

その構文を䜿甚する可胜性がある堎合は2぀ありたす。

// in a signature declaration
declare function foo<[...T]>(...args: [...T]): [...T];
// and when type instantiated, so in the usage
type T = [number, string]
foo<T>();
foo<[...T]>();
// the latter can virtually be replaced as
type _T = [...T]; // which is a type operation that should produce [number, string]
foo<_T>();
// and more
type Extended = [boolean, ...T]; // [boolean, number, string]

したがっお、䜿甚法ずしおは、 | 、 & 、 []ような型挔算子にすぎたせん。 しかし、構文がT extends any[]たたはすべおのタプルの基本型ずしお解釈される可胜性があるずいう宣蚀では、それがタプル型でなければならないこずを瀺しおいたす。

@isiahmeadows

タプルタむプをあたりにも倚くの人に広めようずするずどうなりたすか
パラメヌタヌ このような

declare function foo<T>(...args: [...T]): void
foo<[number]>(1, 2); // ok, foo<[number]> is of type (...args: [number]) => void
// [1, 2] is being passed in place of args
// is [1, 2] which is [number, number] assignable to [number]? yes, with current rules
// no error

たた、型パラメヌタが間違った型であるか、で䜿甚されおいる堎合はどうなりたすか
異垞な、朜圚的に誀った堎所

// 1. unusual place
declare foo<T>(x: T, ...ys: [...T]): void
// 1. [...T] can be interpret as a type constraint "must be a tuple type"
// 2. if we call with type specified
foo<number>(1); // number doesn't meet constraint
foo<[number]>(1, 2); // argument of type 'number' is not assignable to parameter 'x' of type '[number]'
foo<[number]>([1], 2); // ok
// 3. if we call without type, it must be inferred
foo(1); // according to current rules, T would be inferred as '{}[]' - base type of all tuples
        // so, argument of type 'number' is not assignable to parameter 'x' of type '{}[]'
foo([1, 2], 2); // T is inferred as '[number, number]
                // rest arguments of type '[number]' are not assignable to rest parameters 'ys' of type '[number, string]'
foo([1], 2, 3); // T is '[number]',
                // x is of type '[number]',
                // ys is of type '[number]',
                // rest arguments are of type '[number, number]' which is assignable to '[number]',
                // no error

// 2. bad type
declare foo<T>(...xs: [...T]): void
foo<number>(2); // type 'number' doesn't meet constraint

これらのものをタプルずしお衚すこずの利点はただわかりたせん。 さらに、 <T>ではなく<...T>ずしお宣蚀する必芁があるず思いたす。 前に蚀ったように、タプル型は、型システムの任意の長さの型シヌケンスに䜿甚するのに適切なデバむスずは芋なされおいたせん。 人々が望む衚珟床のためにこれが必芁であるず私はただ確信しおいたせん。

もっず衚珟力があるず思いたすが、型パラメヌタヌの䜍眮に「spread」挔算子があるず、RESTパラメヌタヌを2回持぀こずができないのず同じように、REST匕数を1回だけキャッチするように制限されたす。 したがっお、 <...T>ず<A, B, C>䞎えられるず、 Tはそれらを[A, B, C]ずしおキャッチしたす。 たた、 <...T, ...U>はあいたいであるため、衚珟できたせん。 [A, B, C], []たたは[A, B], [C]などです。

次の動䜜で関数を衚珟したいずしたす。

declare function foo(a: A, b: B): R;
declare function boo(c: C, d: D, e: E): U;

let combined: (a: A, b: B, c: C, d: D, e: E) => [R, U] = combine(foo, boo);

// so the signature could be:

declare function combine<R, U, ???>(
  f1: (...args: [...T1]) => R,
  f2: (...args: [...T2]) => U):
    (...args: [...T1, ...T2]) => [R, U];

// if ??? is '...T1, ...T2'
combine<R, U, A, B, C, D, E> // what will be T1 and T2 ?
combine<R, U, ...[A, B, C], ...[D, E]> // ok ? so we will preserve spread to specific positions. so then
combine<...[R, U], A, ...[B, C, D], E> // will be restricted.
// however, ES6 allows to do it with function arguments
f(1, 2, 3);
f(...[1, 2], 3);
f(...[1], ...[2, 3]);

// if ??? is 'T1 extends TupleBase, T2 extends TupleBase'
// or just '[...T1], [...T2]' as a shortcut for such constraints
combine<R, U, [A, B, C], [D, E]> // pretty explicit, and doesn't occupy spread operator for type arguments

さお、あなたがそれをどのように考えおいるかがわかりたした。 あなたが提案しおいるのは、実際には私が思っおいたものずは異なる機胜のようです。 型パラメヌタヌのシヌケンスをキャプチャするための新しい構成を远加する代わりに、タプル型はすでに型のシヌケンスを衚しおいるため、拡散可胜にする必芁がありたす。 そうすれば、さたざたな長さの耇数のタプルをより透過的な方法で枡すこずができたす。

javascriptでは、 function foo(...rest) { }ではなくfunction foo([...rest]) { }ようになりたす。

説明しおくれおありがずう、それは今私にずっおより理にかなっおいたす。 それは合理的なアプロヌチだず思いたす。

@JsonFreemanその通り

@JsonFreeman質問 [1, 2]が[number]満たす必芁があるのはなぜですか それは私には非垞に奇劙に思えたす。 それが実際に機胜するこずは非垞に驚くべきこずです。 型安党ではありたせん。

ただし、可倉個匕数タむプにタプルが䜿甚されるこずに反察しおいるわけではありたせん私は䞭立であり、正盎でもありたす。

@isiahmeadowsはどのようにしお[1, 2]を[number]眮き換えるこずができないのですか それは間違いなくサブタむプです。 { x: 1, y: 2 }が有効な{ x: number }あるのず同じです

わかった。 郚分的に譲歩したすが、匕数のタプルを受け入れるFunction.prototype.applyを考慮に入れたす。

interface Function<T, U, V> {
    (this: T...args: [...U]): V;
    apply(object: T, args: U): V;
}

呌び出し元があたりにも倚くの匕数に察しおTypeErrorをスロヌした堎合、あたりにも倚くの匕数を枡すず、本来のコンパむル゚ラヌではなく、ランタむム゚ラヌが発生したす。

枡された匕数が倚すぎるず、JS関数がTypeErrorをスロヌするこずは非垞にたれではありたせんか いく぀かの䟋は䜕ですか

@isiahmeadowsは抜象的な䟋ですが、あなたが心配しおいる゚ラヌは次のずおりです。

function f(x: number): void {
  // throw if too many arguments
}
f.apply(undefined, [1,2,3]); // runtime error, no compile-time error
f(1,2,3) // compile-time error and runtime error.

あれは正しいですか

@sandersn 、匕数が倚すぎる堎合のTypeErrorは、JSの粟神に違反するものだず思いたす。通垞、この関数に枡される実際の匕数よりも正匏な匕数の少ない関数を枡すためです。 私たちは単にそれらを䜿甚したせん。 たずえばArray.prototype.forEach

機胜カリヌ化はどうですか ラムダでは、それはおそらくはるかに䞀般的です
およびlodash / fp。

月、2016幎2月29日には、1345には、アナトリヌRessin [email protected]曞きたした

@sandersn https://github.com/sandersn、TypeErrorもオンになっおいるず思いたす
倚くの議論は、JSの粟神に違反するものです。
通垞、実際の匕数よりも圢匏的な匕数が少ない関数を枡したす。
この関数に枡されたす。 私たちは単にそれらを䜿甚したせん。 䟋えば
Array.prototype.forEach

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/5453#issuecomment -190327066
。

@isiahmeadows arguments.length基づくカリヌ化は非垞に䞍安定で、実行時に゚ラヌが発生しやすいず思いたす。 実際のカリヌ化は、議論の䜙地がありたせん。

var plus = x => y => x + y
console.log(plus(3)(4)) // 7
console.log(plus(3,10)(4,20)) // still 7

固定眲名付きの関数をコヌルバックずしおどこかに枡すず、次のように考えたす。 '私の関数は_少なくずも_それらの匕数を期埅したす'

foldlようなものはどうですか

const list = [1, 2, 3]
console.log(foldl((a, b) => a + b, 0, list))
console.log(foldl((a, b) => a + b, 0)(list))
console.log(foldl((a, b) => a + b)(0, list))
console.log(foldl((a, b) => a + b)(0)(list))

これは関数型プログラミングでは非垞に䞀般的です。 そしお最埌を省略
議論はかなり䞀般的です。

月、2016幎2月29日には、13時52分には、アナトリヌRessin [email protected]曞きたした

@isiahmeadowshttps //github.com/isiahmeadowsカリヌ化だず思いたす
aruments.lengthに基づくず、非垞に䞍安定で、実行時に゚ラヌが発生しやすくなりたす。
実際のカリヌ化は、議論の䜙地がありたせん。

var plus = x => y => x + y
console.logplus34// 7
console.logplus3,104,20//ただ7

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/5453#issuecomment -190330620
。

たずえば、 mapぞのコヌルバックずしおそれを枡したい堎合リストの凊理
リストの、あなたはおそらくそれをカレヌしたいず思うでしょう。

2016幎2月29日月曜日、 13  [email protected]は次のように曞いおいたす。

foldlようなものはどうですか

const list = [1, 2, 3]
console.log(foldl((a, b) => a + b, 0, list))
console.log(foldl((a, b) => a + b, 0)(list))
console.log(foldl((a, b) => a + b)(0, list))
console.log(foldl((a, b) => a + b)(0)(list))

これは関数型プログラミングでは非垞に䞀般的です。 そしお最埌を省略
議論はかなり䞀般的です。

月、2016幎2月29日には、午埌1時52アナトリヌRessin [email protected]
曞きたした

@isiahmeadowshttps //github.com/isiahmeadowsカリヌ化だず思いたす
aruments.lengthに基づくず、非垞に䞍安定で、実行時に゚ラヌが発生しやすくなりたす。
実際のカリヌ化は、議論の䜙地がありたせん。

var plus = x => y => x + y
console.logplus34// 7
console.logplus3,104,20//ただ7

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/5453#issuecomment -190330620
。

私はそれが䞻にそれに぀いおだず思いたす

type T = [number, string];
var a: T = [1, "a", 2]; // valid

// in this cases tuple types or parameter types cannot be inferred:
f(...a, true); // you could think number,string,boolean were passed, but weren't
const c = [...a, true]; // you could think that is of type [number, string, boolean] but it's not
// according to current rules, the best inferred types might be [number, string, number|string|boolean]

// same manner with variadic kinds, types are constructed properly:
type R = [...T, boolean]; // [number, string, boolean]

だから私は6229を提案したした

[1, 2]が[number]満たすかどうかの質問は、質問しお議論するのに有効な質問です。 しかし、それはスプレッド可胜なタプル機胜ず䜕の関係があるのでしょうか

タプルの可倉個匕数アプリケヌションが䜙分な匕数を無芖する必芁があるかどうかです
か吊か。 このオヌバヌロヌドされた関数は、私の懞念をさらに詳しく説明するはずです。

declare function foo(x: number, ...args: string[]): void
declare function foo<T>(...args: [...T]): void
foo<[number]>(1, 2)

// This will always fail
declare function foo(x: number, ...args: string[]): void
declare function foo<T>(x: T): void
foo<number>(1, 2)

月、2016幎2月29日には、18時47分ゞェむ゜ン・フリヌマン[email protected]は曞きたした

[1、2]が[数倀]を満たすかどうかの質問は、質問するのに有効な質問です。
ず蚎論。 しかし、それはスプレッド可胜なタプル機胜ず䜕の関係があるのでしょうか

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/5453#issuecomment -190453352
。

そしおこれが、実甚的な理由から、RESTパラメヌタヌのようなものを奜む理由です
可倉個匕数型。

2016幎2月29日月曜日、1900 Isiah [email protected]は次のように曞いおいたす。

タプルの可倉個匕数アプリケヌションが䜙分なものを無芖する必芁があるかどうかです
匕数かどうか。 このオヌバヌロヌドされた関数は、私の
懞念。

declare function foo(x: number, ...args: string[]): void


declare function foo<T>(...args: [...T]): void
foo<[number]>(1, 2)

// This will always fail
declare function foo(x: number, ...args: string[]): void
declare function foo<T>(x: T): void
foo<number>(1, 2)

月、2016幎2月29日には、午前18時47ゞェむ゜ン・フリヌマン[email protected]
曞きたした

[1、2]が[数倀]を満たすかどうかの質問は、質問するのに有効な質問です。
ず蚎論。 しかし、それはスプレッド可胜なタプル機胜ず䜕の関係があるのでしょうか

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/5453#issuecomment -190453352
。

@JsonFreemanこれは、型ず配列/タプルのspread挔算子のためです。 スプレッド型挔算子が「指定された型A 、 B 、およびT = [A]圢匏で蚱可されおいる堎合、 [...T, B]は[A, B] 」 暗黙的に提案されたすその堎合、配列/タプル拡散挔算子ず敎列されたせん。 var a: [A]ずvar b: B䞎えられた堎合、匏[...a, b]の型が[A, B]型であるず蚌明するこずはできたせん。 タプルの珟圚のルヌルによれば、タむプ[A, A|B]であるこずが蚌明される可胜性がありたす。
それはあなたにずっお意味がありたすか たたは、比范衚を䜜成しお、その䞍䞀臎を匷調するこずもできたす。

@Igorbekあなたの蚀っおいるこずがわかりたす。 最終的には、コンパむラヌが凊理する型に぀いお完党な知識を持っおいるが、倀に぀いおは完党な知識を持っおいないずいう事実に起因したす。 特に、この䟋では、倀a長さが䞍明ですが、タむプ[A]長さは既知です。 これが、この目的でタプル型を䜿甚するこずに最初は䞍快だった理由の1぀でした。 しかし、それが深刻な問題かどうかはわかりたせん。

@isiahmeadowsあなたが䜕を求めおいるのかわかりたすが、

タむプセヌフ゜リュヌションは、他の゜リュヌションずより䞀貫性がありたす。
匕数の構文を暡倣した堎合の蚀語。

私のポむントは、RESTパラメヌタヌを効果的に拡散しおいる堎合、次のようになりたす。
正確に匕数タむプであり、それ以䞊ではありたせん。 カレヌ関数にはリタヌンがありたす
匕数の型に䟝存する型。 したがっお、1぀の匕数を適甚しすぎるず
カリヌ化機胜を郚分的に適甚するず、たったく違うものになりたす
タむプ。 タプルのようなRESTタむプを凊理するず、代わりにランタむム゚ラヌが発生したす。
これは決しお良いこずではありたせん。

火、2016幎3月1日には、午前6時07ゞェむ゜ン・フリヌマン[email protected]は曞きたした

@Igorbekhttps //github.com/Igorbekあなたの蚀っおいるこずがわかりたす。
それは最終的に、コンパむラが完党な知識を持っおいるずいう事実から生じたす
それが扱っおいるタむプの、しかし倀の完党な知識ではありたせん。 の
特に、あなたの䟋では、倀aの長さは䞍明ですが、
タむプ[A]の長さは既知です。 これが私が最初にいた理由の1぀でした
この目的でタプル型を䜿甚するこずに䞍快感を芚えたす。 しかし、私にはわかりたせん
それは深刻な問題です。

@isiahmeadowshttps //github.com/isiahmeadowsあなたが䜕を求めおいるのかわかりたす
に぀いおですが、RESTタむプのパラメヌタヌで問題がより明確になるのはなぜですか

—
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/5453#issuecomment -190667281
。

@isiahmeadowsカリヌ化問題のサンプルコヌドを

Restタむプのパラメヌタヌ私がすべおですを䜿甚したずしおも、過剰な匕数を蚱可しないこずを明瀺的に決定する必芁があるず思いたすが、おそらくそうすべきである

@sandersn @JsonFreeman

type FullCurry<T> = ((initial: T, xs: T[]) => T) | ((initial: T) => (xs: T[]) => T)
declare function foldl<T>(func: (acc: T, item: T) => T, initial: T, xs: T[]): T
declare function foldl<T>(func: (acc: T, item: T) => T): FullCurry<T>
declare function foldl<T>(func: (acc: T, item: T) => T, initial: T): (xs: T[]) => T

interface Function<T, R, ...A> {
    apply<U extends T>(inst: U, args: [...A]): R
    apply(inst: T, args: [...A]): R
}

function apply(reducer: (initial: number) => number): (number[]) => number {
    reducer.apply(undefined, [0, []])
}

const func = apply(foldl<number>((x, y) => x + y))

func([1, 2, 3]) // Runtime error

バリ゚ヌションも远加したす。 提案からの可倉個匕数カレヌの䟋を芋おみたしょう

function curry<...T,...U,V>(f: (...ts: [...T, ...U]) => V, ...as:...T): (...bs:...U) => V {
    return ...b => f(...as, ...b);
}

それで、私はそれを䜿い始めたした

function f(a: number, b: string, c: string) { return c.toUpperCase(); }
var a: [number, string] = [1, "boo", 2]; // valid
const cf = curry(f, ...a); // cf is of type string => string
cf("a"); // runtime error

@isiahmeadowsそれらが

@Igorbek問題は可倉個匕数型シヌケンスの衚珟方法ではないずいう点で、あなたの䟋は䌌おいるず思いたす。 問題を匕き起こすのは、それらをタプルに広げる機胜です。

@JsonFreeman私がこの振る舞いに反察するのはそれだけではあり

class A {}
class B {}
class C {}

declare function foo(a: A, b: B): C;

// This should not work
let value: [A, B, C]
foo(...value)

それは明確ですか

@isiahmeadows実際に

@JsonFreeman
私はそれがすべきではないず感じおいたす。 それが私の最倧の異議です。 もしそうなら、それは朜圚的に危険だず思いたす。

質問 retの掚定リタヌンタむプはどうあるべきですか

declare function foo(a: A, b: B, c: C, d: D): D
let ret = foo.bind(...[new A(), new B(), new D()])

これは実際にはかなり重芁です。

その最埌の䟋は間違いなく機胜しないようです。 function.bindが実際に正しく機胜する堎合は、基本的に、型のシヌケンスを敎列させるメカニズムが必芁です。 バむンドする匕数の型が元の関数の匕数ず照合され、残りが戻り型になる、統䞀に䌌たものが必芁になりたす。

ずはいえ、提案たたは議論された内容では、タプルの远加の匕数が蚱可されおいるかどうかに関係なくそれを凊理できるものはないようですが、䜕かを芋逃した可胜性はありたす。

最倧の問題は、各パラメヌタヌの型がスプレッド型ず照合される、ある皮のタプルパタヌンマッチングを、その問題を修正するために型パラメヌタヌLiveScript / CoffeeScriptの匕数で実行する必芁があるこずだず思いたす。 そうでなければおそらく䞍可胜です。 そしお、それがどれほど耇雑かに぀いおは、それを実装するために頑匵っおください。 笑顔

@JsonFreeman

たたは、より正確に蚀うず、熱心な察怠惰な意味で厳密ではないタむプチェックが機胜する必芁がありたす。 たた、自己再垰型など、他の倚くの䟿利なものぞの扉を開くので、ずにかく、それはおそらく可倉個匕数型よりも䟿利な拡匵機胜だず思いたす。

// I hate this idiom.
interface NestedArray<T> extends Array<Nested<T>> {}
type Nested<T> = T | NestedArray<T>

// I would much prefer this, but it requires non-strict type checking.
type Nested<T> = T | Nested<T>[]

ありがたいこずに、非厳密な型チェックは、以前はチェックに倱敗したコヌドのみが機胜するようになったずいう点で、玔粋にノヌブレヌクの倉曎である必芁がありたす。

これは、非垞に耇雑な型の眲名が必芁になるずいう事実を陀けば、おそらくFunction.prototype.bindの適切な型指定を劚げる最倧の問題です。

それは興味深い぀ながりです。 しかし、私はそれらが関連しおいるずは確信しおいたせん。 再垰型の問題は、ゞェネリックスのキャッシュポリシヌず、コンパむラヌでの型゚むリアスの衚珟の結果です。 すべおの情報がそこにあり、邪魔になるのはコンパむラの蚭蚈だけです。

タプルパタヌンマッチングの堎合、タプルに察しお䞀臎する匕数の数を垞に把握できるずは限りたせん。 配列をbindの匕数に分散するず、結果のコヌルバックにいく぀残っおいるかわかりたせん。

@JsonFreemanずは

@JsonFreeman

たた、型を厳密にチェックしないず、 Function.prototype.bindその問題を簡単に修正できるほどの怠惰が可胜になりたす。 このような怠惰があるず、次のようにしおその型を実珟できたす型宣蚀で耇数のRESTパラメヌタヌが問題ない堎合を陀き、それらをシヌケンスするためにタプル構文が必芁になりたす。

interface Function {
    bind<R, T, ...X, ...Y>(
        this: (this: T, ...args: [...X, ...Y]) => R,
        thisObject: T,
        ...args: [...X]
    ): (this: any, ...rest: [...Y]) => R
}

なぜこれは掚論するために非厳密な型チェックを必芁ずするのでしょうか 関数をチェックするには、残りのタむプを段階的に掚枬する必芁がありたす。 次のこずを考えるず、次のようにチェックする必芁がありたす。

// Values
declare function func(a: number, b: string, c: boolean, d?: symbol): number

let f = func.bind(null, 1, "foo")

// How to infer
bind<R, T, ...X, ...Y>(
    this: (this: T, ...args: [...X, ...Y]) => R,
    thisObject: T,
    ...args: [...X]
): (this: any, ...rest: [...Y]) => R

// Infer first type parameter
bind<number, T, ...X, ...Y>(
    this: (this: T, ...args: [...X, ...Y]) => number,
    thisObject: T,
    ...args: [...X]
): (this: any, ...rest: [...Y]) => number

// Infer second type parameter
bind<number, any, ...X, ...Y>(
    this: (this: any, ...args: [...X, ...Y]) => number,
    thisObject: any,
    ...args: [...X]
): (this: any, ...rest: [...Y]) => number

// Infer first part of rest parameter
bind<number, any, number, ...*X, ...Y>(
    this: (this: any, ...args: [number, ...*X, ...Y]) => number,
    thisObject: any,
    ...args: [number, ...*X]
): (this: any, ...rest: [...Y]) => number

// Infer second part of rest parameter
bind<number, any, number, string, ...*X, ...Y>(
    this: (this: any, ...args: [number, string, ...*X, ...Y]) => number,
    thisObject: any,
    ...args: [number, string, ...*X]
): (this: any, ...rest: [...Y]) => number

// First rest parameter ends: all ones that only uses it are fully spread
bind<number, any, number, string, ...Y>(
    this: (this: any, ...args: [number, string, ...Y]) => number,
    thisObject: any,
    ...args: [number, string]
): (this: any, ...rest: [...Y]) => number

// Infer first part of next rest parameter
bind<number, any, number, string, boolean, ...*Y>(
    this: (this: any, ...args: [number, string, boolean, ...*Y]) => number,
    thisObject: any,
    ...args: [number, string]
): (this: any, ...rest: [boolean, ...*Y]) => number

// Infer second part of next rest parameter
// Note that information about optional parameters are retained.
bind<number, any, number, string, boolean, symbol?, ...*Y>(
    this: (
        this: any,
        ...args: [number, string, boolean, symbol?, ...*Y]
    ) => number,
    thisObject: any,
    ...args: [number, string]
): (this: any, ...rest: [boolean, symbol?, ...*Y]) => number

// Second rest parameter ends: all ones that only uses it are exhausted
bind<number, any, number, string, boolean, symbol?>(
    this: (this: any, ...args: [number, string, boolean, symbol?]) => number,
    thisObject: any,
    ...args: [number, string]
): (this: any, ...rest: [boolean, symbol?]) => number

// All rest parameters that are tuples get converted to multiple regular
parameters
bind<number, any, number, string, boolean, symbol?>(
    this: (
        this: any,
        x0: number,
        x1: string,
        x2: boolean,
        x3?: symbol
    ) => number,
    thisObject: any,
    x0: number,
    x1: string
): (this: any, x0: boolean, x1?: symbol) => number

// And this checks

これは、非厳密な型チェックの仕組みです。 芋た瞬間ではなく、必芁に応じおタむプを掚枬したす。 間違ったタむプが倱敗するように、2぀のパスを組み合わせるこずができたすそしおそうすべきです。 䟋

let f = func.bind(null, 1, Symbol("oops"))

// How to infer
bind<R, T, ...X, ...Y>(
    this: (this: T, ...args: [...X, ...Y]) => R,
    thisObject: T,
    ...args: [...X]
): (this: any, ...rest: [...Y]) => R

// Infer first type parameter
bind<number, T, ...X, ...Y>(
    this: (this: T, ...args: [...X, ...Y]) => number,
    thisObject: T,
    ...args: [...X]
): (this: any, ...rest: [...Y]) => number

// Infer second type parameter
bind<number, any, ...X, ...Y>(
    this: (this: any, ...args: [...X, ...Y]) => number,
    thisObject: any,
    ...args: [...X]
): (this: any, ...rest: [...Y]) => number

// Infer first part of rest parameter
bind<number, any, number, ...*X, ...Y>(
    this: (this: any, ...args: [number, ...*X, ...Y]) => number,
    thisObject: any,
    ...args: [number, ...*X]
): (this: any, ...rest: [...Y]) => number

// Infer second part of rest parameter
bind<number, any, number, string, ...*X, ...Y>(
    this: (this: any, ...args: [number, string, ...*X, ...Y]) => number,
    thisObject: any,
    ...args: [number, symbol /* expected string */, ...*X] // fail!
): (this: any, ...rest: [...Y]) => number

この堎合、期埅されるパラメヌタヌは、深さ優先の反埩を実行しお、そのラりンドで最初に掚枬されるパラメヌタヌである必芁がありたす。 この堎合、その怜玢で最初に掚枬されたのは文字列であり、蚘号は文字列に割り圓おるこずができないため、これは倱敗したす。


そしお、これずFunction.prototype.applyを入力しようずしたため、RESTタむプを適甚するためにタプルを䜿甚するこずに぀いおの私の意芋が倉わりたした。

interface Function {
    apply<T, R, ...X>(
        this: (this: T, ...args: [...X]) => R,
        thisArg: T,
        args: [...X]
    ): R
}

他のいく぀かのメモ

  1. 配列ずタプルをRESTタむプのパラメヌタヌずしお拡散する方法が必芁です。

ts interface Foo extends Function<void, ...string[]> {}

  1. コンストラクタヌず呌び出し可胜オブゞェクトには2぀の別個の型が必芁であり、関数は2぀の和集合です。 呌び出し可胜オブゞェクトは呌び出し可胜むンタヌフェむスを実装する必芁があり、クラスコンストラクタヌは構築可胜むンタヌフェむスを実装する必芁があり、ES5関数は2぀の和集合を実装する必芁がありたす。
  2. Function.prototype.bindずその友人は、関数のすべおのオヌバヌロヌドをチェックする必芁がありたす。 その䜜業が耇数ある堎合は、それらすべおの和集合を返す必芁がありたす。

ただし、䟋のこれらの型パラメヌタヌは、実際にはバむンド眲名の型パラメヌタヌではありたせん。 それらは関数型に属したす。 しかし、そうです。2぀のRESTパラメヌタヌを䜿甚したり、2぀のRESTタむプのパラメヌタヌをタプルに分散したりできれば、これを蚘述できるずいう考えです。

バむンドの眲名を十分に柔軟にするには、 ...Xず...Yの境界を呌び出しごずに決定する必芁がありたす。 掚枬する必芁がありたす。 ただし、眲名で...Xを単独で䜿甚する堎合は問題になりたす。 この堎合、境界は決定されおいたせん。 䟋えば

interface SomeType<T, R, ...X, ...Y> {
     someMethod(someArgs): [...X]; // No way of knowing how long X is 
}

そしお、オヌバヌロヌドは関数型にずっおかなり問題です。 オヌバヌロヌド間でパラメヌタヌを混合および照合できるため、各匕数で共甚䜓型を芁玠ごずに䜿甚する必芁はないず思いたす。 それはあなたが意味したこずですか

@JsonFreeman

_TL; DR氎平方向の改行にスキップしたす。 新しい、より実甚的なアむデアがありたす。_

  1. はい、私は圌らが本圓にFunction自䜓に属しおいるこずを知っおいたす。
  2. そのような問題が、Haskellの意味での非厳密な型マッチングが必芁だず私が蚀った理由です。 型を正垞に解決するこずはできたせん。これを行うには、反埩的な遅延怜玢が必芁になるためです。 アルゎリズムで決定するこずは可胜ですが、C ++のように通垞は远跡する必芁のないものを远跡する必芁がありたす。
  3. 2぀の匕数が分離しおいる堎合䟋のように、コンパむラヌは文句を蚀う必芁がありたす。 そしお、その状況は、むンタヌフェヌスなどの各可倉個匕数のタむプレベルの䟝存関係分析で怜出できたす。 たた、簡単ではありたせんが、型宣蚀自䜓を読み取るずきに確認できたす実際には、その盎埌。

私も考えおいたすが、問題のメ゜ッドだけでこの皮の状況を定矩する方がもう少し実珟可胜かもしれたせん。 たた、あなたがほのめかしたそのような朜圚的な問題を怜出するこずは、はるかに簡単か぀迅速になりたす。

interface Function<R, T, ...A> {
    // Split it up for just this method, since it's being resolved relative to the
    // method itself.
    bind[...A = ...X, ...Y](
        this: (this: T, ...args: [...X, ...Y]) => R,
        thisObject: T,
        ...args: [...X]
    ): (this: any, ...rest: [...Y]) => R
}

解決するのがはるかに難しい朜圚的な他の問題がありたすそしお、なぜそれを_n _分割ではなく2に制限する必芁があるず思うのですか

declare function foo<...T>[...T = ...A, ...B, ...C](
    a: [...A, ...C],
    b: [...A, ...B],
    c: [...B, ...C]
): any

// This should obviously check, but it's non-trivial to figure that out.
let x = foo<
    boolean, number, // ...A
    string, symbol,  // ...B
    Object, any[]  // ...C
>(
    [true, 1, {}, []],
    [true, 1, "hi", Symbol()],
    ["hi", Symbol(), {}, []]
)

_ここでCS理論に深く入り蟌んでいる堎合は申し蚳ありたせん..._

はい、それは正しい考えだず思いたす。 きれいではありたせんが、 Functionの型匕数を知っおいるので、 bindを正しく入力する他の方法は考えられたせん。 究極のこずは、境界を掚枬しなければならないずいうこずです。 たた、組み合わせお爆発する可胜性のある任意の数の境界ではなく、1぀の境界を掚枬する必芁があるように、2぀のバケットに制限する必芁があるこずに同意したす。

私たちが考えおいなかった問題がもっずある可胜性がありたす。

@JsonFreemanもう1぀の問題は、 curryようなものです。 私はそれを正しくタむプできるものをただ思い付いおいたせん。 そしお、私ができるようになるたでにはしばらく時間がかかりたす。 そのようなプロセスを思い付くには、Haskellのような深刻なタむプのハッキングを行う必芁がありたす。

ある皮の提案がいく぀かのBluebird関数でどのように機胜するかを考えたす。

interface PromiseConstructor {
    // all same type
    all<T>(promises: PromiseLike<T>[]):  Promise<T[]>;
    join<T>(...promises: PromiseLike<T>[]):  Promise<T[]>;
    // varying types
    all<...T>(promises: [...PromiseLike<T>]): Promise<[...T]>;
    join<...T>(...promises: [...PromiseLike<T>]): Promise<[...T]>;
    // this is sketchy...    ^
}

interface Promise<T> {
    // all same type
    then<U>(onFulfill: (values: T) => U): Promise<U>;
    spread<U>(onFulfill: (...values: T) => U): Promise<U>;
}
interface Promise<...T> {
    // varying types
    then<U>(onFulfill: (values: [...T]) => U): Promise<U>;
    spread<U>(onFulfill: (...values: [...T]) => U): Promise<U>;
}

䞊蚘のall<...T>(promises: [...PromiseLike<T>]): Promise<...T>;解決策はありたすか

@DerFlatulator

PromiseConstructorの私の倧きなコメントを参照しおください。 たた、Promiseむンタヌフェヌスを修正しお、私の提案に少し近づけたした。

interface PromiseConstructor {
    new <T>(callback: (
        resolve:
        (thenableOrResult?: T | PromiseLike<T>) => void,
        reject: (error: any) => void
    ) => void): Promise<T, [T]>;
    new <...T>(callback: (
        resolve:
        (thenableOrResult?: [...T] | PromiseLike<[...T]>) => void,
        reject: (error: any) => void
    ) => void): Promise<[...T], ...T>;

    // all same type
    all<T>(promises: PromiseLike<T>[]):  Promise<T[], ...T[]>;
    join<T>(...promises: PromiseLike<T>[]):  Promise<T[], ...T[]>;

    // varying types
    all<...T>(promises: [...PromiseLike<T>]): Promise<[...T], ...T>;
    join<...T>(...promises: [...PromiseLike<T>]): Promise<[...T], ...T>;

    // all<...T>(promises: [...PromiseLike<T>]): Promise<[...T], ...T> should
    // expand to this:
    //
    // all<T1, T2, /* ... */>(promises: [
    //     PromiseLike<T1>,
    //     PromiseLike<T2>,
    //     /* ... */
    // ]): Promise<[T1, T2, /* ... */], T1, T2, /* ... */>;
    //
    // This should hold for all rest parameters, potentially expanding
    // exponentially like ...Promise<[Set<T>], ...Thenable<T>> which should
    // expand to something like this:
    //
    // Promise<[Set<T1>], Thenable<T1>, Thenable<T2> /* ... */>,
    // Promise<[Set<T2>], Thenable<T1>, Thenable<T2> /* ... */>,
    // // etc...
}

interface Promise<T, ...U> {
    // all same type
    then<V>(onFulfill: (values: T) => V): Promise<[V], V>;
    spread<V>(onFulfill: (...values: T) => V): Promise<[V], V>;

    // all same type, returns tuple
    then<...V>(onFulfill: (values: T) => [...V]): Promise<[...V], ...V>;
    spread<...V>(onFulfill: (...values: T) => [...V]): Promise<[...V], ...V>;

    // varying types
    then<V>(onFulfill: (values: [...U]) => V): Promise<[V], V>;
    spread<V>(onFulfill: (...values: [...U]) => V): Promise<[V], V>;

    // varying types, returns tuple
    then<...V>(onFulfill: (values: [...U]) => [...V]): Promise<[V], ...V>;
    spread<...V>(onFulfill: (...values: [...U]) => [...V]): Promise<[V], ...V>;
}

[...Foo<T>]が[Foo<T1>, Foo<T2>, /*... Foo<TN>*/]堎合、 [...Foo<T,U>]は構文゚ラヌですか、それずも組み合わせ展開ですか

@DerFlatulator

  1. TたたはUがRESTパラメヌタヌである堎合、通垞どおりに展開されたす。 TがRESTパラメヌタヌであるずするず、 [Foo<T1, U>, Foo<T2, U>, /*... Foo<TN, U>*/]たす。
  2. 䞡方がRESTパラメヌタヌであり、それらの長さを正しく掚枬できる堎合は、組み合わせ展開である必芁がありたすTの長さ×Uの長さ。
  3. どちらもRESTパラメヌタヌでない堎合は、構文゚ラヌです。

実甚䞊の理由から、3぀以䞊のRESTパラメヌタヌに匷く反察し、残りのパラメヌタヌを分割する必芁がある堎合は、メ゜ッドごずにのみ分割する必芁があるこずに泚意しおください。 このようなもの

interface Function<R, T, ...A> {
    // Split it up for just this method, since it's being resolved relative to the
    // method itself.
    bind[...A = ...X, ...Y](
        this: (this: T, ...args: [...X, ...Y]) => R,
        thisObject: T,
        ...args: [...X]
    ): (this: any, ...rest: [...Y]) => R
}

_誰かがより良い構文を思い付くこずができれば、私はすべおの耳です。私はそれが奜きではありたせんが、芖芚的に矛盟しないものを思い぀くこずはできたせん。_

@isiahmeadows

2.の堎合、拡匵はどのような順序で行われたすか

[
Foo<T1, U1>, Foo<T2, U1>, /*... */ Foo<TN,U1>,
Foo<T1, U2>, Foo<T2, U2>, /*... */ Foo<TN,U2>,
/* ... */
Foo<T1, UN>, Foo<T2, UN>, /*... */ Foo<TN,UN>
]

たたは逆に

[
Foo<T1, U1>, Foo<T1, U2>, /*... */ Foo<T1,UN>,
Foo<T2, U1>, Foo<T2, U2>, /*... */ Foo<T2,UN>,
/* ... */
Foo<TN, U1>, Foo<TN, U2>, /*... */ Foo<TN,UN>
]

このあいたいさは混乱を匕き起こしたせんか おそらく、1぀の次元に制限するのが賢明でしょう。


分割構文の代替案

interface Function<R, T, ...A> {
    bind<[...X, ...Y] = [...A]>(
        this: (this: T, ...args: [...X, ...Y]) => R,
        thisObject: T,
        ...args: [...X]
    ): (this: any, ...rest: [...Y]) => R
}

@DerFlatulator

私は2番目を期埅したす。 そしお、それが䞀貫しおそれである限り、人々はすぐにそれに慣れおしたうので、それがあたりにも倚くの混乱を匕き起こすこずはないず思いたす。 それはたた、圌らが䜕をしおいるのかを知っおいる人々、たたはそもそも必芁性を疑うべき人々によっおのみ実際に遭遇するであろう珍しい゚ッゞケヌスです。

私はたた、あなたが最初の郚分を拡匵し、次に最初の郚分の各郚分に぀いお2番目を拡匵しおいるずきにそれを芋おいたす。 この擬䌌コヌドのように

for (let TT of T) {
  for (let UU of U) {
    expand(TT, UU);
  }
}

䞊蚘のアむデアのいく぀かを繰り返したす...

interface Function<TReturn, TThis, ...TArgs> {
    bind<
        [...TBound, ...TUnbound] = [...TArgs],
        TNewThis
    >(
        thisObject: TNewThis,
        ...args: [...TBound]
    ): Function<TReturn, TNewThis, ...TUnbound>
}

ここで、 [...TBound, ...TUnbound] = [...TArgs]長ために有効です...TBoundの長さから知られおいるargs 。 たた、 TThisのタむプを倉曎するこずもできたす。

このアプロヌチの問題の1぀は、 thisバむンドできるのは1回だけであるずいうこずです。たずえば、次のようになりたす。

interface IFoo { a: number }
interface IBar extends IFoo { b: boolean }
function f(a: number) { }

let x = f.bind(<IBar>{ a: 1, b: false }, 2); // inferred type: Function<number, IBar>
let y = x.bind(<IFoo>{ a: 1 }) // inferred type: Function<number, IFoo>

yの掚定タむプは正しくありたせん。 Function<number, IBar>である必芁がありたす。 これが問題になるかどうかはわかりたせんが、それを解決するには、 <T>構文にロゞックを導入する必芁がありたす。

オプション1

interface Function<TReturn, TThis, ...TArgs> {
    bind<
        [...TBound, ...TUnbound] = [...TArgs],
        TNewThis = TThis is undefined ? TNewThis : TThis
    >(
        thisObject: TNewThis,
        ...args: [...TBound]
    ): Function<TReturn, TNewThis, ...TUnbound>;
}

オプション2

interface Function<TReturn, TThis, ...TArgs> {
    bind<
        [...TBound, ...TUnbound] = [...TArgs],
        TThis is undefined,
        TNewThis
    >(
        thisObject: TNewThis,
        ...args: [...TBound]
    ): Function<TReturn, TNewThis, ...TUnbound>;

    bind<
        [...TBound, ...TUnbound] = [...TArgs],
        TThis is defined
    >(
        thisObject: any,
        ...args: [...TBound]
    ): Function<TReturn, TThis, ...TUnbound>;
}

ただし、それはこの提案の範囲倖である可胜性がありたす。

型拡散挔算子を䜿甚しおこのような拡匵を蚱可するべきではないず思いたす。 スプレッド挔算子は、配列スプレッド挔算子およびオブゞェクト/プロパティスプレッド挔算子ず完党に䞀臎する「ブラケットリムヌバヌ」ず考えおいたすステヌゞ2の提案。 比范しおください

let a =        [1, 2];
let b = [0, ...a     , 3];
//      [0, ...[1, 2], 3]
//      [0,     1, 2 , 3]  // removed brackets

let c =               { a: 1, b: "b" };
let d = { e: true, ...c               , f: 3 };
//      { e: true, ...{ a: 1, b: "b" }, f: 3 };
//      { e: true,      a: 1, b: "b"  , f: 3 };

新しい型のセットを構築するためにそれを拡匵するこずを提案しおいたす

<...T> = <A, B, C>
...U<T> = <U<A>, U<B>, U<C>>

党く違う操䜜です。 必芁に応じお、次のような高次の構造でモデル化できたす。

<...(from R in T select U<R>)> // linq-like
<...(T[R] -> U<R>)> // ugly

@Igorbek挔算子を䜿甚しお、䜕を展開するかを決定するのはどうですか

interface PromiseConstructor {
    all<
      ...T, 
      [...TThen] = ...(PromiseLike<@T> | @T)
    >(
      promises: [...TThen]
    ): Promise<[...T], ...T>;
}

...Foo<<strong i="9">@T</strong>, U>は[Foo<T1,U>, /*...*/, Foo<TN,U>]たす。

...(PromiseLike<@T> | @T)はに展開されたす
[PromiseLike<T1>|T1, /*...*/, PromiseLike<TN>|TN]

いく぀かの構文の遞択肢

  • ...Foo<&T,U>
  • (T) Foo<T,U>
  • (...T => Foo<T,U>)
  • for (T of ...T) Foo<T,U>

ここで@Igorbekに同意したす。 少なくずもこの段階では、可倉個匕数型パラメヌタヌのより基本的な問題を解決しようずしおいるこずを考えるず、型のシヌケンスのマッピングは優先事項のようには芋えたせん。

私はそれを犁止するこずにそれほど問題はありたせん少なくずも最初は。なぜなら、その振る舞いはかなり䞀矩的であり、2人の異なる人々が2぀の非垞に異なるこずを期埅するかもしれないからです。 TypeScriptは最初に高次の型モデルを持っおいる必芁があるのである意味でmapが型にpingを実行する、少なくずも今のずころ@Igorbekに同意したす。 そしお、より高次のタむプは、あなたがただボルトで留めるこずができるものではありたせん。

だから間違いなく+1それを犁止するために、おそらくかなり長い間。 TypeScriptは機胜的でタむプセヌフな型システムを䜿甚しおいないため、持っおいるのは良いこずですが、実装は非垞に耇雑で、完党にハックする必芁がありたす。

少し遅れお来たすが、 @ Igorbekにも同意したす。 1336で行った私のコメントを繰り返し、明確な「pack」および「unpack」挔算子を持぀C ++パラメヌタヌパッキングからアむデアを借りおいたす。

タむプをタプルにパックするこずは、Typescriptのspread挔算子の䜿甚法ず䞀臎しおいるようです。

let [x, y, ...rest] = [1, 2, 3, 4, 5] // pack
foo(...params) // unpack
let all = [1, 2, ...other, 5] // unpack

// keep in mind this is already implemented, which kind of similar to mapping types
function map(arr) { ... }
let spreadingmap = [1, 2, ...map(other), 5];

これにより、 <...T_values> = [T1, T2, T3, etc...]の掚論がはるかに簡単になりたす。

C ++はパックにspread挔算子を䜿甚し、アンパックに省略蚘号を䜿甚したすが、䞡方にspreadを䜿甚するず、Typescriptずの䞀貫性が高たりたす。

module Promise {
  function all<...T_values>(   // pack into a tuple of types, conceptually identical to rest parameters
      values: [ (<PromiseLike<T*>> ...T_values) ]  // unpack, cast, then repack to tuple
  ): Promise<T_values> // keep it packed since T_values is a tuple of whatever types
}

@isiahmeadows @JsonFreemanマッピングなしでこのすべおのポむントは䜕でしょうか

たた、1336で提起されたように、可倉個匕数Array.flattenどうですか

@jameskeaneその前半は最初のアむデアでしたが、ミドルレストパラメヌタヌ䞀郚のAPIにはありたすの堎合に぀いおは説明しおいたせん。

function foo<...T>(a: Foo, b: Bar, ...rest: [...T, Baz]): Foo;

たた、 Function.prototype.applyずFunction.prototype.call比范も十分にカバヌしおいたせん。

1336に関しおは、これを介しお同様に実装される可胜性がありたす。

angular.module('app').controller(['$scope', function($scope: ng.IScope) { /*etc...*/ }]);

interface IModule {
  controller(injectable: [...string[], () => any]);
}

私は远い぀いおきお、タプル型が厳密な長さであるず玠朎に想定しおいるこずに気づきたした。 どのimoが最も盎感的です。 では、厳密な長さのタプル型6229を取埗するず仮定するず、問題は䜕ですか

@isiahmeadows䞊蚘のミドルレストパラメヌタヌの堎合の䟋では、厳密な長さのタプルを䜿甚するこずで解決されたせんか arr = [...other, 123]展開するスプレッドず同じように...rest: [...T, Baz]読んでいたす。 これはあなたがcurryで提起したのず同じ問題ですよね

applyずcallに぀いおは、亀差する型でカバヌされおいたせんか ずにかく、 Functionむンタヌフェむスに型を蚭定するこずの䟡倀を実際に理解しおいるわけではありたせん。

// as in
const t: [any, string] & [number, any] = [1, "foo"]

interface Function<R, T, ...A> {
    bind<...Y, ...Z>(
        this: (this: T, ...args: A & [...Y, ...Z]) => R, // tricky bit, luckily intersecting tuples is pretty easy
        thisObject: T,
        ...args: Y
    ): (this: any, ...rest: Z) => R
}

@jameskeane

珟圚の可倉個匕数の提案は、6229が実際に受け入れられるこずを前提ずしおいたす぀たり、タプルはデフォルトで厳密です。

func.apply 、 func.bind 、 func.call 、および_.curry堎合、唯䞀の問題はfunc.bind 、 _.curry 、ず友達、たたはより䞀般的には郚分適甚を䜿甚するもの。 たた、分離するRESTパラメヌタヌを遞択できる必芁がありたす。これは、実際にはメ゜ッドごずにのみ実行できたす。

callずapplyは非垞に簡単です。

type Callable<R, T, ...A> = (this: T, ...args: [...A]) => R;

interface Function<R, T, ...A> {
    call(this: Callable<R, T, ...A>, thisArg: T, ...args: [...A]): R;
    apply(this: Callable<R, T, ...A>, thisArg: T, args: [...A]): R;
}

bindはもっず難しいでしょう。 分割パラメヌタは、最初の分割された半分が完党に解凍されるたで、珟圚の堎合のように熱心にではなく、必芁に応じお䞀臎させる必芁がありたす。 これは構文ずしお実装する必芁がありたす。これにより、コンパむラはそれを区別し、䜕も評䟡せずに型を正しく識別できたす。

// Function.prototype.bind
type Callable<R, T, ...A> = (this: T, ...args: [...A]) => R;
type Constructible<R, ...A> = new (...args: [...A]) => R;

interface Function<R, T, ...A> {
    // my proposed syntax for splitting a rest parameter
    bind[[...A] = [...X, ...Y]](
        this: Callable<R, T, ...A>
        thisArg: T,
        ...args: [...X]
    ): Callable<R, any, ...Y>;

    bind[[...A] = [...X, ...Y]](
        this: Constructible<R, ...A>
        thisArg: T,
        ...args: [...X]
    ): Constructible<R, ...Y>;

    bind[[...A] = [...X, ...Y]](
        this: Callable<R, T, ...A> & Constructible<R, ...A>
        thisArg: T,
        ...args: [...X]
    ): Callable<R, T, ...Y> & Constructible<R, ...Y>;
}

curryは、 f(1, 2, 3) === f(1, 2)(3) === f(1)(2, 3) === f(1)(2)(3)こずを知っおいる必芁があるため、非垞に困難です。 。 bindように、RESTパラメヌタヌを2぀に分割する機胜が必芁なだけでなく、メ゜ッドごずに非垞にプリミティブなパタヌンマッチングを実行する機胜も必芁です。

interface Curried<R, T, ...XS> {
    // none passed
    (): this;

    // all passed
    (this: T, ...args: [...XS]): R;
}

interface CurriedMany<R, T, X, ...YS> extends Curried<R, T, X, ...YS>  {
    // penultimate case, constraint that ...YS contains no parameters
    [[...YS] = []](arg: X): Curried<R, T, X>;

    // otherwise, split rest into ...AS and ...BS, with `A` used as the pivot
    // (basically, default case)
    [[...YS] = [...AS, A, ...BS]](
        ...args: [X, ...AS]
    ): CurriedMany<R, T, A, ...BS>;
}

function curry<R, T>(f: (this: T) => R): (this: T) => R;
function curry<R, T, X>(f: (this: T, arg: X) => R): Curried<R, T, A>;
function curry<R, T, X, ...YS>(
    f: (this: T, arg: X, ...args: [...YS]) => R
): CurriedMany<R, T, X, ...YS>;

curryを远加しおもチュヌリング完党になるずは思いたせんが、近いでしょう。 それを劚げる䞻なものは、特定の型の専門分野に䞀臎する胜力だず思いたすC ++、Scala、Haskell、チュヌリング完党型システムを備えた3぀の蚀語はすべお持っおいたす。

@sandersn䞊蚘の䟋は衚瀺されたせんでしたが、可倉個匕数パラメヌタヌの制玄に぀いお質問できたすか

次の䟋を考えおみたしょう。

interface HasKey<T> {
    Key(): T;
}

class Row<...T extends HasKey<X>, X> {
    // ...
}

_ちなみに、 Xをリストする必芁があるずいう芁件を削陀する可胜性に぀いおは、 https //github.com/Microsoft/TypeScript/issues/7848を参照しお

ここで、制玄が次のいずれであるかに぀いお、あいたいさが生じる可胜性がありたす。

  1. (...T) extends HasKey<X>たたは
  2. ...(T extends HasKey<X>)

この䟋では、2を想定しおいたす。

これらの皮類の制玄1および/たたは2は可胜ですか

@myitcv 2がおそらく最善のルヌトですが、制玄をチェックするために既存のロゞックを再利甚するこずは理にかなっおいたす。

さお...私はちょうど䜕かに気づきたした可倉個匕数型を含む配列はどのようになりたすか より具䜓的には、以䞋のargはどのタむプですか

function processItems<...T>(...args: [...T]): void {
    for (const arg of args) { // Here
        process(arg);
    }
}

argsの芁玠タむプは䜕であるかを尋ねおいるず思いたす。 タプルの堎合、これは通垞、芁玠の共甚䜓タむプであるず思いたす。 私はそれをタむプするより良い方法を考えるこずができたせん。

@sandersnこの機胜のステヌタスに぀いおコメントできたすか たくさんの議論があったように感じたすが、その機胜に぀いお明確な蚈画があるようには思えたせんが、それは正しいですか

@JsonFreeman私は具䜓的にargが䜕であるかを尋ねおいたした。 私の意芋では、それがあるべきany私のオリゞナル䟋えば、およびItem<T>以䞋でずT F-有界

function processItems<...T extends Item<T>>(...args: [...T]): void {
    for (const arg of args) { // Here
        process(arg);
    }
}

これは、タむプをロヌカルで解決できるようにするためです。 事前に型がわからない堎合は、関数を呌び出すたびに関数内で型を蚈算する必芁がないため、コンパむルが倧幅に高速化されたす。 単䞀の匕数の型だけが必芁な堎合は、 typeof arg十分であり、おそらく短くなるこずに泚意しおください。

申し蚳ありたせんが、元の䟋では、タむプはT必芁がありたす。 実際、2番目の䟋では、Tである必芁があるず思いたす。

私は2番目にItem<any>を意味したした...ごめんなさい。

Tである必芁があるず蚀ったずき、Tはタむプであるず想定しおいたしたが、この機胜の芁点は、Tがタむプではないずいうこずだず思いたす私は思いたす。 そうですね、あなたの䟋ではanyずItem<any>になるはずです。

しかし、もっず広く蚀えば、チヌムが2.0以降でこの機胜をどれほど積極的に怜蚎しおいるかに興味がありたす。 私は匷い意芋を持っおいたせん、ただ疑問に思っおいたす。

必ずしもTである必芁はないず思うのは、 Tが䜕であるかがわからないためです。 もちろん、可倉個匕数Tが可倉個匕数型リストの単䞀の型を衚すか、拡散された堎合はリスト自䜓、぀たりTが枡されるすべおの匕数のサブタむプであるこずを意味する堎合を陀きたす。匕数...T 、および[...T]はT[]割り圓おるこずができたす。

たたは、すべおの䞍明確な専門甚語で私が䜕を意味するかを明確にするために、コヌドに関しお私が䜕を意味するかを次に瀺したす。

// To put it into code
function foo<...T>(list: [...T]): void {
    // This is allowed
    let xs: T[] = list

    // This is allowed
    let list2: [...T] = list

    // This is not allowed
    let list1: [...T] = xs

    // This is allowed
    let item: ?T = null

    // This is not allowed, since it's not immediately initialized
    let other: T

    for (let arg of args) {
        // This is allowed
        let alias: T = arg

        // This is allowed
        let other: ?T = arg

        // This is allowed, since `item` is defined upwards as `?T`
        item = arg

        // This is allowed, since you're doing an unsafe cast from `?T` to `T`.
        alias = item as T
    }
}

しかし、それはおそらくもっず理にかなっおいるでしょう、そしおそれははるかに柔軟でしょう。

それはただ私たちの䟿利なリストにありたすが、それは䞻に図曞通の䜜者に興味があり、たずもな回避策_n_オヌバヌロヌドがあるので、私は積極的に取り組んでいたせん。 掚枬しなければならないのであれば、2.1は可胜ですが、可胜性は䜎いず思いたす。

オブゞェクトのREST / Spread2103を適切にサポヌトするこずを玄束した堎合、可倉個匕数の皮類は、型を拡散しお䞀床にすべおを実行するこずを正圓化するのに十分近い可胜性がありたす。 スプレッドタむプは、 { ...T, x: number, ...U, y: string, ...V }ように芋えるオブゞェクトタむプのバリアントです。

n overloads回避策は、クラスやむンタヌフェむスでは機胜しないこずに泚意しおください。これは、この機胜に特に関心がありたす。

@sandersn 「_n_overloads」のプルリク゚ストは、 this入力を䜿甚しお、関数のbind 、 apply 、およびcallに招埅されたすか これは倚くの人にずっお蚱容できる䞀時的な劥協案であり、䞀郚のプロゞェクトの過皋でかなりの数のバグを芋぀ける可胜性があるず思いたす。

@isiahmeadows

必ずしもTである必芁はないず思うのは、Tが䜕であるかわからないからです。

Tは可倉個匕数型のタプル型であるずいう合意があったように私には思えたした。 元の䟋では、 arg型はタプル芁玠の型ず同じになりたす @JsonFreemanが「芁玠の共甚䜓型」ず述べたように今のずころ、typescriptがタプルを残りずしお䜿甚するこずをサポヌトしおいるず想像しおくださいタむプ5331。

function processItems<...T>(...args: T): void {
  for (const arg of args) { // Here - arg:number|string|boolean
    const other: ??? = arg; // I think the issue is, how to _represent_ this type?
  }
}
processItems(1, 'foo', false); // T is tuple [number, string, boolean]

この提案ずは別に、タプルの「芁玠タむプ」を衚す方法があるはずだず思いたす。 これは、スプレッドの別の甚途、぀たり䞊蚘のように...T :: number|string|booleanたす。 タプル型を拡散するず、その芁玠型になりたす。

for (const arg of args) {
  const cst: ...T = arg;
}

// also, even without variadic types...
type Record = [number, string];
function foo(args: Record) {
  for (const arg in args) {
    const cst: ...Record = arg;
  }
}

これを念頭に眮いお、他の䟋

function foo<...T>(...list: T): void {
  let xs: T[] = [list, list] // array of the variadic tuple type

  // This is allowed
  let list5: (...T)[] = [...list]

  // This is *not* allowed
  let list2: [...T] = list

  // This is not allowed
  let list1: [...T] = xs

  // This **is** allowed
  // single element tuple, of variadic union
  // i.e. with number|string|boolean
  //      list4 = [1] or list4 = ['foo'] or list4 = [false]
  let list4: [...T] = [list[n]]

  // This **is**  allowed
  let other: T;

  // This is allowed
  let another: ...T;

  for (let arg of args) {
    another = arg; // allowed, if spreading the tuple is the union type

  }
}

私の圓初の目暙を芋倱うこずなく、匷く型付けされたPromise.all欲しかった...

declare module Promise {
  function all<...T>(promises: Promise<...T>[]): T; // means promises is an array of promises to the union type, not what I wanted.

  // Then we need something like, which is now very confusing
  function all<...T>(promises: [...Promise<T*>]): T; 
}}

@sandersn他の芁求された機胜がこれに䟝存し始めおいるので、優先順䜍を䞊げるこずができるでしょうか bind 、 callなどのタむピングはこれに䟝存し、ESバむンド構文が出おくるかどうかはそれに䟝存するので、今では颚倉わりなラむブラリの䜜者がい぀もあなたを悩たせおいるよりもこれに乗っおいたす。 :)

これを远加するのが特に建蚭的であるずいうわけではありたせんが、これら2぀の機胜が2.1になったらずおも嬉しいです。 私は少なくずも1぀のラむブラリRxJSを知っおいたす。これらの機胜によっおコヌドベヌス自䜓が改善されるだけでなく、コヌドの消費も倧幅に軜枛され、バグが発生しやすくなりたすAngular 2を䜿い始める3人に1人は、むンポヌトがないために噛たれたす。監芖可胜なプロトタむプにパッチが適甚されおいるオペレヌタヌの堎合。 これは、保守可胜な関数型コヌドを曞きたいず考えおいる人々にずっお、本圓に画期的な機胜になるでしょう。

これを䜿甚しお、 _.extend完党な型定矩を提䟛できたすかその戻り型はすべおのパラメヌタヌの共通郚分です。

declare module underscore {
  function extend<A, B, C, D, ...>(a: A, b: B, c: C, d: D, ...): A&B&C&D&...;
}

珟状ではありたせん。 可倉個匕数の皮類の新しい挔算子おそらくず呌ばれるの詳现を瀺す提案の拡匵が必芁です。 @kitsonkは、このコメントで、この挔算子を以前に提案したした。
珟圚、この機胜は他のいく぀かのすぐに重芁なものの䞋にあるので、私はしばらくこの提案を芋おいたせん。

完党な可倉個匕数の皮類を提䟛するわけではありたせんが、10727は゜リュヌションの䞀郚ですそしお、私たち@dojoが抱える課題に察凊する可胜性がありたす。

聞いおよかった それはただ実際には可倉個匕数の皮類ではありたせんが。 :(たずえば、今週Object.assignず入力しようずするず、ここたで到達したした。

interface Object {
  // binary version
  assign<T,U>(target: T, source: U): { ...T, ...U };
  // variadic version: bind a variadic kind variable ...T
  // and then spread it using SIX dots
  assign<...T>(...targets: ...T): { ......T };
}

「6ドット」構文は、タプルの皮類の倉数のオブゞェクトスプレッドであるこずに泚意しおください。これに぀いおは、䞊蚘では実際には説明しおいたせん。

@sandersn

ではObject.assignがその目暙を倉異させるため、特に、それはあなたは、このための基準点を持っおいる必芁があるだろう、この方法を入力し、技術的にあたりにもinferrably匱い少しはあるがのサブセットをキャプチャするこずができたす

assign<T>(target: T, ...sources: Partial<T>[]): T;

それに関する䞍具合は、タヌゲットを倉曎し、その構造タむプを所定の䜍眮に倉曎するこずです。

@isiahmeadowsの堎合、掚論によりTがsourcesアカりンティングタむプなしでtargetタむプに修正されたす。 非可倉バヌゞョンで今すぐ詊すこずができたす

declare function _assign<T>(target: T, source: Partial<T>): T;
_assign({}, { a: 10 }); // T is {}

すでに述べたように、 assignは_スプレッドタむプ_10727を䜿甚し、次のように定矩できたす。

// non variadic
declare const assign: {
  <T>(target: T): T;
  <T, S>(target: T, source: S): {...T, ...S};
  <T, S1, S2>(target: T, source1: S1, source2: S2): {...T, ...S1, ...S2};
};
// variadic
declare function assign<T, [...S]>(target: T, ...sources: [...S]): {...T, ...[...S]};

_泚私はただタプルベヌスの構文[...T]を䞻匵しおいたすが、これは私にずっおはるかに意味がありたす。_

@sandersnずころで、可倉個匕数の皮類がい぀䞊陞するかに぀いおの曎新はありたすか 2.2でそれを芋るチャンスはありたすか
そしお、構文に関しお、あなたはただ構文に関するフィヌドバックを受け入れたすか、それずもあなたはすべおそれに同意したすか

構文ず䜎レベルのセマンティクスには、ただ明確なコンセンサスがありたせん。

火、2016幎12月13日には、13時26分むゎヌルOleinikovの[email protected]は曞きたした

@sandersn https://github.com/sandersnずころで、い぀曎新されたすか
可倉個匕数の皮類が䞊陞する予定ですか 2.2でそれを芋るチャンスはありたすか
そしお、構文に関しお、あなたはただ構文に関するフィヌドバックを受け入れたすか
あなたはすべおそれに同意したすか

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/Microsoft/TypeScript/issues/5453#issuecomment-266819647 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/AERrBIa5fE8PSk-33w3ToFqHD9MCFoRWks5rHuM5gaJpZM4GYYfH
。

この問題の状況に぀いお䜕か考えはありたすか

それで、あなたが考えおいるオプションは䜕ですか これはチヌムの議題ですか それは私が繰り返し遭遇する型システムの唯䞀の匱点です。 私には2぀のナヌスケヌスがありたす。 単玔で耇雑ですが、より䞀般的なものです。

簡単なのは、タプル型によっおのみサブタむプ化できるTuple extends any[]スヌパヌタむプを远加するこずです。 スプレッドはany[]サブタむプである必芁があるため、これは機胜したす。

declare interface Plugin<A: Tuple, P> {
  (...args: A): P | Promise<P>
}

const p: Plugin<[string, { verbose: boolean }], int> =
  (dest, { verbose = false }) => 4

珟時点では、 ...args: T[]は眲名の最埌でのみ蚱可されおいたす。

耇雑なナヌスケヌスでは、眲名内のどこでも合法であるために...args: Tupleが必芁になりたすタプルは固定長であるため、問題ありたせん。

/**
 * Takes a function with callback and transforms it into one returning a promise
 * f(...args, cb: (err, ...data) => void) => void
 * becomes
 * g(...args) => Promise<[...data]>
 */
function promisify<A extends Tuple, D extends Tuple, E>
    (wrapped: (...args: A, cb: (error: E, ...data: D) => void) => void)
    : ((...args: A) => Promise<Data>) {
  return (...args) => new Promise((resolve, reject) =>
    wrapped(...args, (e, ...data) =>
      e ? reject(e) : resolve(data)))
}

const write: ((fd: number, string: string, position?: number, encoding?: string)
              => Promise<[number, string]>) =
  promisify(fs.write)

ええ、私は昚日TypeScriptを䜿い始めたばかりで、関数をラップするために䜿甚しおいる単䞀のデコレヌタのために、関数を自動的に入力するこずはすでに䞍可胜になっおいたすもちろん手動で入力するこずもできたすこれが最初のこずです私はから始めおみたした

function portable(func) {
    return function(...args) {
        if (this === undefined) {
            return func(...args)
        } else {
            return func(this, ...args)
        }
    }
}

事実䞊、デコレヌタが行うのは、関数をメ゜ッドずしおも呌び出せるようにするこずです。これにより、関数をメ゜ッドずしおアタッチしお同じように機胜させるこずができたす。基本的な䟋ずしお、 Arrayプロトタむプにパッチを適甚する悪い䟋を瀺したす。 flatMap基本バヌゞョンで

function _flatMap<T, R>(
    array: T[],
    iteratee: (item: T) => R[]
): R[] {
    let result: R[] = []
    for (const item of array) {
        for (const value of iteratee(item)) {
            result.push(value)
        }
    }
    return result
}

const flatMap = portable(_flatMap)
Array.prototype.flatMap = flatMap

flatMap([1,2,3,4], x => [x, x])
// Is the same as
[1,2,3,4].flatMap(x => [x, x])
// Is the same as
flatMap.apply([1,2,3,4], [x => [x, x]])
// Is the same as
flatMap.call([1,2,3,4], x => [x, x])

flatMap  _flatMap のタむプが次のずおりであるこずは明らかです。

function flatMap<T, R>(this: T[], iteratee: (item: T) => R[]): R[]
function flatMap<T, R>(this: undefined, array: T[], iteratee: (item: T) => R[]): R[]

ただし、 _flatMapからパラメヌタヌの型を抜出しお、装食された関数の型定矩内で䜿甚するこずができないため、 typesをポヌタブルに远加する方法はありたせん。この提案で想像できたす。次のように蚘述したす。

// First argument to func is required for portable to even make sense
function portable<T, R, ...Params>(func: (first: T, ...rest: Params) => R) {
    // The arguments of calling with this is undefined should be simply
    // exactly the same as the input function
    function result(this: undefined, first: T, ...rest: Params): R
    // However when this is of the type of the first argument then the type
    // should be that the parameters are simply the type of the remaining
    // arguments
    function result(this: T, ...rest: Params): R
    function result(...args) {
        if (this === undefined) {
            return func(...args)
        } else {
            return func(this, ...args)
        }
    }
    return result
}

TypeScriptでの最初の経隓を瀺し、可倉個匕数ゞェネリックが重芁である理由の別のケヌスを瀺しおいるので、これを共有したかっただけです。

@sandersn 

それはたずもな回避策を持っおいたす-nオヌバヌロヌド

技術的には正しくありたせんが、これはここでの珟実を完党には反映しおいないず思いたす。 ええ、技術的にはこれがなくおも、オヌバヌロヌドがこのスレッドで蚀及されおいる関数を入力するのを防ぐこずはできたせんでした。 それでも、この小さな䞍䟿は、これたでのずころ、そのような過負荷ベヌスの゜リュヌションがlib.d.tsなっおいないこずを意味しおいたす。

実際、このスレッドの倚くは、 ......や、 ...*X 、 [...T = ...A, ...B, ...C]など、元々この提案の䞀郚ではなかったさらに倚くの構文を提案するために、それぞれの関数に取り組むこずに必死に感じおいたす。 [...PromiseLike<T>] 、 <[...X, ...Y] = [...A]> 、および<PromiseLike<T*>> 。

これは、私たち党員がここで問題に取り組んでいるこずを瀺しおいるず思いたす。このようなより匷力な構文が必芁であるずいう䞀般的な感芚を共有しおおり、ここで遞択した方法が問題の解決に圹立぀こずを願っおいたす。

サむドノヌト甚RAMDAのR.path 、我々はただただ難しい順列が爆発しただろう方法タプルのサポヌトを逃した過負荷の千っぜいラむンの入力を生成し、ちょうど終了しないように、実際のプロゞェクトでコンパむルを匕き起こしたしたもう。 そこに䞀芋実行可胜な代替手段ずしお最近発芋された反埩12290。

ちなみに、 @ Artazorず@Igorbekが提案した提案に぀いおはただコメントしおいたせん。 それに぀いおどう思いたしたか

ここでそのような基本的な実装および6606に぀いお議論したいのですが、私たちはほが䜕でもできたす。 これを説明するために、ここでいく぀かの解決策を提䟛したすが、さらに質問をするこずもできたす。

たず、 ...挔算子を実装

v ... for | 定矩キャプチャ| 䜿甚拡散
-|-|-
関数| type Fn = (...args: any[]) => {} | type Returns = typeof fn(...MyTuple); 6606
配列| タむプレベルのタプルの砎棄。 技術的には、むンデックスアクセス+スプレッド右を参照+再垰を䜿甚しお゚ミュレヌトできたす。 | type Arr = [Head, ...Tail];
オブゞェクト| タむプレベルのオブゞェクトの砎棄。 必芁ありたせん。 Omitを䜿甚しおください。12215を参照しおください。 | type Obj = { a: a, ...restObj }; 䞍芁、 Overwriteず同じ、12215を参照
ゞェネリック| 定矩type Foo<...T>行うためにFoo<1, 2, 3> キャプチャ[1, 2, 3 ]にT 。 楜しいですが、どのナヌスケヌスでこれが必芁かわかりたせん。 | 定矩type Bar<A,B,C>行うBar<...[1,2,3]>  A = 1など。 同䞊、これを必芁ずするナヌスケヌスを知らない。
組合ボヌナス|  | type Union = "a" | "b"; type MyTuple = ...Union; // ["a", "b"] 順序は信頌できたせんが、タプルを介したナニオン/オブゞェクトの反埩が可胜です。ずにかく、ここでは範囲倖です。

したがっお、すぐに関連するタむプレベルの...むンスタンスは2぀だけです。 具䜓的には、ここで䜿甚される2぀

declare function f<U, T>(head: U, ...tail: T): [U, ...T];

6606のコンテキストでは、別の関連性がありたす。関数アプリケヌション甚にタプル型を解凍する機胜です䟋 typeof f(...MyTuple) 。 私がここで蚀及したこずを聞いたより難しい問題を解決するには、これらで十分だず思いたす。 ここでいく぀かの゜リュヌションを提䟛しようずするには

@jameskeane 

タプルの「芁玠タむプ」を衚珟する方法があるはずだず思いたす

それらの芁玠の和集合を取埗したい堎合は、私のTupleToUnion参照しおください。

Promise.all

// helpers: `mapTuple` needs #5453 to define, #6606 to use
type TupleHasIndex<Arr extends any[], I extends number> = ({[K in keyof Arr]: '1' } & Array<'0'>)[I];
type Inc = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // longer version in gist
declare function mapTuple<F extends (v: T) => any, Tpl extends T[], T>(f: F, tpl: Tpl): MapFn<F, Tpl, T>;
type MapFn<
    F extends (v: T) => any,
    Tpl extends T[],
    T,
    // if empty tuple allowed:
    // I extends number = 0,
    // Acc = []
    // otherwise:
    I extends number = 1,
    Acc = [F(Tpl[0])]
> = { 1: MapFn<F, Tpl, T, Inc[I], [...Acc, F(Tpl[I])]>; 0: Acc; }[TupleHasIndex<Tpl, Int>];

declare module Promise {
  function all<Promises extends Promise<any>[]>(promises: Promises): typeof mapTuple(<T>(prom: Promise<T>) => T, Promises);
}

@danvk 

_.extend

@sandersn 

Object.assign

これらは䞡方ずも、RamdaのmergeAllの可倉個匕数バヌゞョンです。 6぀のドットは必芁ありたせん

@isiahmeadows 

この問題の状況に぀いお䜕か考えはありたすか
構文ず䜎レベルのセマンティクスには、ただ明確なコンセンサスがありたせん。

私が正しく理解しおいれば、あなたは䞻に、他のいく぀かが提䟛するアプロヌチが、あなたが蚀及したcurryやbindなどのより難しいタむピングぞの取り組みを考慮に入れるかどうかを心配しおいたした。 圌らの提案に続いお、これがその特定のものに぀いおの私の芋解です。
戊略は少し䌌おおり、関数適甚ぞの匕数の型チェックを延期するこずによっお、関数型からタプル型にparams i〜jの型芁件を抜出するずいうのは難しいずいう事実をだたしたす。

// helpers in https://gist.github.com/tycho01/be27a32573339ead953a07010ed3b824, too many to include

// poor man's version, using a given return value rather than using `typeof` based on the given argument types:
function curry<Args extends any[], Ret>(fn: (...args: Args) => Ret): Curried<Args, Ret>;
type Curried<
  ArgsAsked,
  Ret,
  ArgsPrevious = [] // if we can't have empty tuple I guess any[] might also destructures to nothing; that might do.
> = <
  ArgsGiven extends any[] = ArgsGiven,
  ArgsAll extends [...ArgsPrevious, ...ArgsGiven]
      = [...ArgsPrevious, ...ArgsGiven]
  >(...args: ArgsGiven) =>
    If<
      TupleHasIndex<ArgsAll, TupleLastIndex<ArgsAsked>>,
      Ret,
      Curried<ArgsAsked, Ret, ArgsAll>
    >;

// robust alternative that takes into account return values dependent on input params, also needs #6606
function curry<F>(fn: F): Curried<F>;
type Curried<
  F extends (...args: ArgsAsked) => any,
  ArgsAsked extends any[] = ArgsAsked,
  ArgsPrevious = []
> = <
  ArgsGiven extends any[] = ArgsGiven,
  ArgsAll extends [...ArgsPrevious, ...ArgsGiven]
      = [...ArgsPrevious, ...ArgsGiven]
  >(...args: ArgsGiven) =>
    If<
      TupleHasIndex<ArgsAll, TupleLastIndex<ArgsAsked>>,
      F(...[...ArgsPrevious, ...ArgsGiven]), // #6606
      Curried<ArgsAsked, Ret, ArgsAll>
    >;

// bind:
interface Function {
    bind<
        F extends (this: T, ...args: ArgsAsked) => R,
        ArgsAsked extends any[],
        R extends any,
        T,
        Args extends any[], // tie to ArgsAsked
        Left extends any[] = DifferenceTuples<ArgsAsked, Args>,
        EnsureArgsMatchAsked extends 0 = ((v: Args) => 0)(TupleFrom<ArgsAsked, TupleLength<Args>>)
        // ^ workaround to ensure we can tie `Args` to both the actual input params as well as to the desired params. it'd throw if the condition is not met.
    >(
        this: F,
        thisObject: T,
        ...args: Args
    ): (this: any, ...rest: Left) => R;
    // ^ `R` alt. to calc return type based on input (needs #6606): `F(this: T, ...[...Args, ...Left])`
}

ええ、私はたくさんのヘルパヌタむプを䜿甚したした-私たちが持っおいるものでやり遂げようずしたした+もう少しだけで䜕ができるか想像しおください。 私は...... 、 ...*X 、 [...T = ...A, ...B, ...C] 、 [...PromiseLike<T>] 、 <[...X, ...Y] = [...A]> 、たたは<PromiseLike<T*>>にはあたり反察しおいたせん。 しかし、IMOは、たったの...でも、今のずころ実際の問題に察凊するのに圹立ちたす。私はそれが解決されるこずを望んでいたす。

線集 bindの匕数の制玄を解決したした。

おそらくばかげた質問です。 これは、カレヌ関数を正しく入力できるこずは非垞に有望に芋えたす。
しかし、実際のプロゞェクトの䞭には、関数型プログラミング指向のコヌドを入力するのに倚くの時間を費やしたくないものもありたす。
したがっお、 --strictは_tsconfig.json_でデフォルトで有効になっおいるので、コヌドの䞀郚の型チェックを無効にする方法があるかどうか疑問に思っおいたす怠惰たたは時間の䞍足のため。
しかし、私が蚀ったように、それはおそらく愚かな質問です... ^ _ ^

@ yahiko00はちょっずオフトピックですが、 tsconfig excludeセクション、たたは異なるプロゞェクトレベルの異なるtsconfigたす。

たた、別の提案をしたいず思いたす。 &ず|が、次の構文の単䞀のタプル匕数で機胜するようにするこずができたすか。

<...T>(...args:T): ...T&
// is the same as 
<t1, t2, t3>(...args:[t1, t2, t3]): t1 & t2 & t3;
// and
<....T>(...args:T): ...T|
// is the same as 
<t1, t2, t3>(...args:[t1, t2, t3]): t1 | t2 | t3;

@HyphnKnightの䞊蚘の提案は、私がやっおいるこずにも非垞に圹立ちたす。

この提案は積極的に取り組んでいないずいう免責事項を远加したいず思いたす。 しかし、私がこの問題を最初に芋始めたずきに読みたかった「先行技術」の皮類の玙を正確に芋぀けたした http 

埌で参照できるように、ここに残しおおきたす。

私はこれに向けお実隓しおいるいく぀かのPRを開きたした

  • []17884タプルタむプのスプレッドWIP
  • [x]17898残りのパラメヌタを抜出準備完了
  • []18007タむプコヌルWIPで拡散
const c = 'a' + 'b';

問題を解決できたすか c掚論タむプは'ab'ではなくstring

StackOverflowに関連する質問 TypeScriptの明瀺的な最埌の関数パラメヌタヌ

@sandersnあなたの提案は、私が芋る限り、このケヌスをカバヌするでしょう、これは正しいですか

最初の提案から2幎以䞊経っおも、私たちはただ垌望を持ち続けるべきでしょうか

こんにちは
可倉数の配列を受け取り、それらの芁玠を組み合わせお新しい配列を䜜成するゞェネレヌタヌを入力しようずしおいたす。
このゞェネレヌタヌをfor...ofルヌプで䜿甚したいのですが、倀を正しく入力できたせん。
コヌドただ実行しおいないので間違いがあるかもしれたせんが、これが私がやろうずしおいるこずです

function* CombineEveryArgumentWithEveryArgument(...args: any[][]) {
    if (args.length < 1) {
        return [];
    }
    var haselements = false;
    for (var arg of args) {
        if (arg && arg.length > 0) {
            haselements;
        }
    }
    if (!haselements) {
        return [];
    }
    var indexes = [];
    for (var i = 0; i < args.length; i++) {
        indexes.push(0);
    }
    while (true) {
        var values = [];
        //One item from every argument.
        for (var i = 0; i < args.length; i++) {
            values.push(args[i][indexes[i]]);
        }
        if (indexes[0] + 1 < args[0].length) {
            yield values;
        }
        else {
            return values;
        }
        //Increment starting from the last, until we get to the first.
        for (var i = args.length; i > 0; --i) {
            if (indexes[i]++ >= args[i].length) {
                indexes[i] = 0;
            }
            else {
                break;
            }
        }
    }
}

䜿甚䟋

for (let [target, child] of
    CombineEveryArgumentWithEveryArgument(targetsarray, childrenarray)) {

䞭間倉数を䜜成せずに、タヌゲットず子の入力を取埗する方法を理解するこずはできたせん。

このようなものがいいでしょうか

function * generator<...T[]>(...args: T[]): [...T]

@Griffork正しい方法は、この提案が実装されるたで、関数に倚くのオヌバヌロヌドを䜜成するこずです。
たずえば、promise.allタむプを参照しおください
https://github.com/Microsoft/TypeScript/blob/master/lib/lib.es2015.promise.d.ts#L41 -L113

この構文は非垞に玛らわしいず思いたす。

function apply<...T,U>(ap: (...args:...T) => U, args: ...T): U {

これは私にずっおはるかに自然に感じたす

function apply<T, U>(ap: (...args: T) => U, args: T): U {

実行時のRESTパラメヌタヌは配列であり、珟圚TSでこれを行うこずができたす。

function apply<T, U>(ap: (...args: T[]) => U, args: T[]): U {

したがっお、 argsがT配列であるずいう制限を取り陀き、代わりにTSコンパむラがTタプル型を掚枬できるようにするのは論理的であるように思われたす。

function apply(ap: (...args: [number, number]) => number, args: [number, number]): number {

タプルに぀いおいく぀かの懞念が提起されおおり、すべおを完党に理解しおいるわけではありたせんが、珟圚の提案では、開発者がい぀...を䜿甚する必芁があるかを理解するのが難しいこずを考慮したかっただけです。タむプの䜍眮にあり、タプルははるかに盎感的です。

...は、 [...T, ...U]ように、2぀のタプルタむプを連結するこずには意味がありたす。

@felixfbecker
の提案

function apply<...T,U>(ap: (...args:T) => U, ...args: T): U {

Tは動的に䜜成されたタプル型であるため、 stringずintを関数に枡すず、 Tは[string, int] 。
これは、次のようなパタヌンを動的に衚珟したい堎合に特に興味深いものです。

function PickArguments<T>(a: T[]): [T];
function PickArguments<T, U>(a: T[], b: U[]): [T, U];
function PickArguments<T, U, V>(a: T[], b: U[], c: V[]): [T, U, V];
//More overloads for increasing numbers of parameters.

//usage:
var [a, b, c] = PickArguments(["first", "second", "third"], [1, 2, 3], [new Date()]);
var d = b + 1; //b and d are numbers.
var e = c.toDateString(); //c is a date (autocompletes and everything), e is a string.

珟時点では、可倉数の匕数を取り、それらを䞀般的に入力する関数を䜜成する堎合は、関数に指定できる可胜性のある匕数の数ごずに、䞀般化されたオヌバヌロヌドを䜜成する必芁がありたす。 ...T提案により、基本的に、コンパむラヌに関数定矩を自動的に生成させるこずができたす。

あなたの提案

function apply<T, U>(ap: (...args: T) => U, args: T): U {

すべおのパラメヌタヌが同じタむプずしお扱われるように匷制し、より具䜓的なタむプチェックを行うこずはできたせん。 たずえば、䞊蚘の䟋では、すべおの戻り倀はanyたす。

たた、䜙分な...は非垞に読みにくいず思いたす。
@felixfbeckerのアむデアのように、私はする必芁がないず思いたす

function apply<...T, U>(ap: (...args: ...T) => U, args: ...T): U {...}

apply<...T,読むずきに最初に頭に浮かぶのは、それが拡散挔算子であるずいうこずですが、実際には拡散はたったく行いたせん。

@Griffork 、あなたの䟋では、 Tはただ[string, int]たす。
これが、 @ felixfbeckerが「TSコンパむラがTのタプル型を掚枬できるようにする代わりに」、少なくずも私が理解しおいる方法で意味するこずです。

すべおのパラメヌタヌが同じタむプずしお扱われるように匷制し、より具䜓的なタむプチェックを行うこずはできたせん。 たずえば、䞊蚘の私の䟋では、すべおの戻り倀はany型になりたす。

@Grifforkいいえ、私の考えでは、 args配列のタプル型を掚枬し、タプル内の䜍眮によっお各パラメヌタヌに独自の型を䞎えたす。 ...args: T[]は、それらすべおを同じ型Tに匷制したすが、 ...args: T 珟圚はコンパむル゚ラヌですはTタプル型を掚枬したす。

apply <... Tを読むずきに最初に頭に浮かぶのは、それが拡散挔算子であるずいうこずですが、実際には拡散はたったく行いたせん。

@unionalは同意したす、それはたさに混乱が生じるずころです。

@unional
私もスプレッド挔算子ずしお読み、「䜿甚するたびにこのタむプをスプレッドする」ず読みたした。
私にずっお、これを読んで

function apply<T, U>(ap: (...args: T) => U, args: T): U {

Tは䜕かの配列たずえばstring[] であるず思いたす。

そしおこれを読んで

function apply<T, U>(ap: (...args: T[]) => U, args: T[]): U {

すべおの匕数がタむプT  stringなどの1぀のタむプに割り圓お可胜であるず思いたす。

䞊蚘の提案のポむントは、ゞェネリックスが任意の数の型を衚珟できるようにするこずを暗黙的に回避するこずでした。

@felixfbecker
線集
ああ、わかりたした。 それでも、それが盎感的だずは思わないでください。

Tは䜕かの配列たずえばstring []であるず思いたす。

タプルは「䜕かの配列」であり、固定長で各芁玠の特定の型を持぀単なる配列です。たずえば、 [string, number] vs (string | number)[] 、これはバむンドされおおらず、どの芁玠に䜕があるかを宣蚀したせんタむプ。

では、実際にその動䜜が必芁な堎合は、䜕を入力したすか

正確にどのような動䜜を参照しおいるかはわかりたせんが、「すべおのパラメヌタヌを同じタむプにする」ず想定しおいたす。これは、 ...args: T[]によっお実珟されたす。

私もスプレッド挔算子ずしお読み、「䜿甚するたびにこのタむプをスプレッドする」ず読みたした。

だから混乱しおいるず思いたす。
拡散するずきは、それを実行するだけで、「拡散可胜」なものを宣蚀するこずはありたせん。

const a = { x: 1, y: 2 }
const b = { ...a }

// likewise
function appendString<T>(...args: T): [...T, string] {
  args.push('abc')
  return args
}

うん。 ゞェネリック型匕数が「読み取り可胜」である必芁があるこずを宣蚀したい堎合ES仕様では、反埩可胜でなければならないこずを意味したす、TypeScriptでextendsしおそれを衚珟する方法がすでにありたす。

function foo<T extends Iterable<any>>(spreadable: T): [...T, string] {
  return [...spreadable, 'abc']
}

const bar = foo([1, true])
// bar is [number, boolean, string]

もちろん、RESTパラメヌタヌの堎合、それはIterableだけでなく、配列であるこずが知られおいたす。

これは、私たちが蚀っおいるこずはすでに提案されおいたす https 

しかし、残りは1぀の座垭で消費するには長すぎたす。 🌷

タプル連結が着陞しおいる堎合は、教䌚番号を実装できたす やったヌ

type TupleSuc<T extends [...number]> = [...T, T['length']];
type TupleZero = [];  // as proposed, we need empty tuple
type TupleOne = TupleSuc<TupleZero>;
type Zero = TupleZero['length'];
type One = TupleOne['length'];

たた、条件型の再垰が機胜しおいる堎合は、必芁な長さのタプルを䜜成できたす。

type Tuple<N extends number, T = TupleZero> = T['length'] extends N ? T : Tuple<N, TupleSuc<T>>;
type TupleTen = Tuple<10>;
type Ten = TupleTen['length'];

このスレッドをすべお読んだずは思いたせんが、ゞェネリックパラメヌタヌに...Tれおいるず混乱する堎合は、
倀レベルの砎壊構文をさらにミラヌリングしお、 [...T]を䜿甚するようにしおみたせんか。
タむプレベルの匕数の䜍眮は、タむプレベルのタプルの堎合、タむプを非構造化したすか これも必芁になりたす
タプルを䜿甚しおRESTパラメヌタヌを入力できるようにしたす。これにより、呌び出しサむトで次のようになりたす。
TypeScriptの堎合

const first = (a: number, b: string) => 
;
const second = (...ab: [number, string]) => 
;

first(12, "hello"); // ok
second(12, "hello"); // also ok

INB4「しかしそれはタむプ指向の攟出です」–いいえ。 これは䜕も倉曎せず、 firstただ2぀ありたす
個別の匕数が発行されおも、 secondはただ1぀のREST匕数がありたす。 倉曎されるのは
呌び出しサむトで、TypeScriptはsecondのパラメヌタヌがタプルず順番に䞀臎するこずを確認したす。
[number, string] 。

ずにかく、 [...Type]構文を認めるず仮定するず、次のようにapplyず曞くこずができたす。

function apply<
  [...ArgumentsT], // a type-level tuple of arguments
  ResultT
>(
  // the call site of `toApply` function will be used to infer values of `ArgumentsT`
  toApply:   (...arguments: ArgumentsT) => ResultT,
  arguments: ArgumentsT
) :
  ResultT
{
  // 

}

// NB: using my preferred formatting for complex type-level stuff; hope it's readable for you
// this is entirely equivalent to OP's notation version:
function apply<[...T], U>(ap: (...args: T) => U,  args: T): U {
  // 

}

// so at the call site of
const fn = (a: number, b: string, c: RegExp) => 
;

// we have `ArgumentsT` equal to [number, string, RegExp]
apply(fn, [12, "hello" /s+/]); // ok, matches `ArgumentsT`
apply(fn, [12, /s+/]); // not ok, doesn't match `ArgumentsT`

[...Type]構文は完党に倀レベルの砎壊ずしお動䜜し、分割が可胜になりたす
必芁に応じお、タむプレベルのタプルを結合したす。

type SomeType  = [string, number, "constant"];
type OtherType = ["another-constant", number];

type First<[First, ..._]> = FirstT;
type Rest<[_, ...RestT]> = RestT;
type Concat<[...LeftT], [...RightT]> = [...LeftT, ...RightT];
type FirstTwo<[FirstT, SecondT, ..._]> = [FirstT, SecondT];

// has type `string`
const aString: First<SomeType> =
  "strrriiing";
// has type `[number, "constant"]
const numberAndConstant: Rest<SomeType> =
  [42, "constant"];
// has type `[string, number, "constant", "another-constant", number]`
const everything: Concat<SomeType, OtherType> =
  ["herpderp", 42, "constant", "another-constant", 1337];
// has type `[string, number]`
const firstTwo: FirstTwo<SomeType> =
  ["striiiing", 42];

これを䜿甚しおcurry関数を入力する方法の䟋

type Curried<
  [...ArgumentsT]
  ResultT,
  ArgumentT      = First<ArgumentsT>,
  RestArgumentsT = Rest<ArgumentsT>
> =
  // just ye olde recursione, to build nested functions until we run out of arguments
  RestArgumentsT extends []
    ? (argument: ArgumentT) => ResultT
    : (argument: ArgumentT) => Curried<RestArgumentsT, ResultT>;

// NB. with more complex generic types I usually use generic defaults as a sort-of
// of type-level variable assignment; not at all required for this, just nicer to read IMO

function curry<
  [...ArgumentsT],
  ResultT
>(
  function: (...arguments: ArgumentsT) => ResultT
) :
  Curried<ArgumentsT, ResultT>
{
  // do the magic curry thing here
}

// or in the short indecipherable variable name style

function curry<[...T], U>(fn: (...args: T) => U): Curried<T, U>
{
  // 

}

// this should let you do this (using `fn` from before)
const justAddRegex = curry(fn)(123, "hello");

justAddRegex(/s+/); // ok, matches the arguments of `fn`
justAddRegex(123); // not ok, doesn't match the arguments of `fn`

䞀郚の型匕数は型レベルのタプルであるず蚀えるこずも圹立぀ず思いたす。
ある皮の。 問題は、2.7私は思う以降のタプルの割り圓お可胜性がどのようにかかるかずいうこずです。
タプルの長さを考慮に入れる–_任意のタむプレベルのタプル_の抂念を衚珟したす。 しかし倚分䜕かのような
[...]は機胜したすか 匷い意芋はありたせんが、コンセプトに名前を付けおいただければず思いたす。

// bikeshed me
type OnlyTuplesWelcome<ArgumentT extends [...]> = ArgumentT;

その堎合、䞊蚘の[...ArgsT]構文は、基本的にArgsT extends [...]省略圢になりたす。
タむプレベルのデストラクチャリングを䜿甚するずいうこずは、タむプがタむプレベルのタプルになるずいう制玄を意味したす。

考え

@jaen 

(...ab: [number, string]) => 


ええ、それは4130のように芋えたす。 18004で䜕かを詊したしたが、私のアプロヌチは少しハッキヌでした合成ノヌド。

タプルを衚珟する際に、誰かがany[] & { 0: any }を䜿甚しおいるのを芋たこずがありたす。これは、空のタプルタむプfwiwたで機胜するず思いたす。 私は個人的にはあたり気にしたせんでしたが、ほずんどはany[] 。

RxJSはこれをあちこちで必芁ずしおいたす。 最も重芁なのはObservable.prototype.pipe 、珟圚倚くのオヌバヌロヌドがありたすが、垞に「もう1぀のレベル」を远加するように求められたす。

2番目の@benleshでは、RXJSを広範囲に䜿甚しおおり、パむプ関数にこれが必芁です。

私はppipeの䜜者です。これは、RXJSのパむプ関数ず同様に、これを必芁ずしたす。 ここに暡様が芋えるず思いたす^^

私はruntypesの䜜成者で和集合ず共通郚分を衚珟するために切実に必芁ずされおいたす。 唯䞀の䞍完党な回避策は、巚倧な過負荷です。

https://github.com/pelotom/runtypes/blob/master/src/types/union.ts

🀢

ラムダの皮類を曞き盎したした。これもpipe 、レンズ、カリヌ化などに必芁です。
カリヌ化によっお過負荷を盎接維持するこずが管理できなくなったため、codegenが必芁でした。 pathタむプは1000行を超えおいたしたが、その時点でオヌバヌロヌドタむプのパフォヌマンスも問題になっおいるこずがわかりたした。

REST匕数の掚枬ず適甚に関する問題は解決されたしたか

function example(head: string, ...tail: number[]): number[] {
  return [Number(head), ...tail]
}

function apply<T, U>(fn: (...args: T) => U, args: T): U {
  return fn.apply(null, args)
}

䞭にTのタむプの堎合はapply(example, ['0', 1, 2, 3])ず掚察される[string, number[]] 、適甚する呌び出しが゚ラヌを発生させるでしょう。

぀たり、Tのタむプは本圓に

type T = [string, ...number[]]

たた

type T =
  {0: string} &
  {[key: Exclude<number, 0>]: number} &
  Methods

確かに奇劙な獣ですが、 ({0: string} & Array<number>)[0]がどのようになるかを考えるず
珟圚string解決されおいたす[1]あたり倉曎せずに゚ンコヌドできるようです
型システムに。

[1]これはバグですか、本圓にstring | numberたすか

この問題の36人の参加者に迷惑をかけお申し蚳ありたせんがヒントこれを䜿甚し

2幎半経っおもただ誰も割り圓おられおいないのは悲しいこずですが、かなり重芁な機胜のようです:(

PS数十のコメントを読んだり、Cmd + Fなどを詊したりしたしたが、この情報は芋぀かりたせんでした。

@brunolemos最新の蚭蚈䌚議で可倉個匕数タむプぞの参照がありたす
https://github.com/Microsoft/TypeScript/issues/23045
この機胜を䜜成するには、最初に、より原始的で抂念を繰り返し䜜成する必芁がありたす。十分な基盀がある堎合は、マむルストヌンに远加するず確信しおいたす。

これは私にはできない

type Last<T extends any[]> =
    T extends [infer P] ? P :
    ((...x: T) => any) extends ((x: any, ...xs: infer XS) => any) ? Last<XS> :

14174の問題ですが、関係ずしお

参照甚の@kgtkrは、コンパむラに再垰を芋逃させるための@fightingcatのトリックを参照しおください。

ありがずう

type Last<T extends any[]> = {
    0: never,
    1: Head<T>,
    2: Last<Tail<T>>,
}[T extends [] ? 0 : T extends [any] ? 1 : 2];

うヌん、質問がありたす。 ミックスむンを凊理するための次のようなコヌドがありたす。

export const Mixed = <

    OP = {}, OS = {}, // base props and state
    AP = {}, AS = {}, // mixin A props and state
    BP = {}, BS = {}, // mixin B props and state
    // ...and other autogenerated stuff
>(

    // TODO: Find a way to write that as ...args with generics:
    a?: ComponentClass<AP, AS>,
    b?: ComponentClass<BP, BS>,
    // ...and other autogenerated stuff

) => {

    type P = OP & AP & BP;
    type S = OS & AS & BS;
    const mixins = [a, b];

    return class extends Component<P, S> {
        constructor(props: P) {
            super(props);
            mixins.map(mix => {
                if (mix) {
                    mix.prototype.constructor.call(this);
                    // some state magic...
                }
            });
        }
    };
};

私はそれを次のように䜿甚したす

class SomeComponent extends Mixed(MixinRedux, MixinRouter, MixinForm) {
     // do some stuff with mixed state
}

適切なタむピング、状態凊理などで期埅どおりに機胜したすが、可倉個匕数の皮類を埅たずに、より短い方法で曞き盎す方法はありたすか 私は今これに぀いお少し銬鹿げおいるず感じおいるからです。

3.0では、restargsをtuppleずしお宣蚀できるようになりたした。

declare function foo(...args: [number, string, boolean]): void;

しかし、逆に取埗しお、指定された関数のタプル型の匕数を取埗するこずは可胜ですか

Arguments<foo>ようなものがいいでしょう。

@whitecolorこれはどうですか

type Arguments<F extends (...x: any[]) => any> =
  F extends (...x: infer A) => any ? A : never;

TS 3.0では、これを今すぐ実行できたす

function compose<X extends any[], Y extends any[], Z extends any[]>(
  f: (...args: X) => Y,
  g: (...args: Y) => Z
): (...args: X) => Z {
  return function (...args) {
    const y = f(...args);
    return g(...y);
  };
}

しかし、単䞀のパラメヌタに察しおタプルむベントを返す関数を宣蚀し、なんらかの方法でvoidを凊理する必芁があるずいう小さな問題がありたす。それ以倖の堎合は、配列ずしお掚枬される戻り型を宣蚀する必芁がありたす:)

https://www.typescriptlang.org/play/index.html#src =0D0A0D0A0D0A0D0A0D0A0D0A0D0Afunction20foo0 3A20void207B0D0A200D0A7D0D0A0D0Afunction20bar03A20void207B0D0A0D0A7D 0D0A0D0Afunction20foo1a3A20string3A205Bstring5D207B0D0A2020return205Ba5D3B0D0A 7D0D0A0D0Afunction20bar1a3A20string3A205Bstring5D207B0D0A2020return205Ba5D3B0D0A 7D0D0A0D0Afunction20foo2a13A20string2C20a23A20boolean3A205Bstring2C20boolean5D207B0D0A20 20return205Ba12C20a25D3B0D0A7D0D0A0D0Afunction20foo21a13A20string2C20a23A20boolean3A205Bstring 5D207B0D0A2020return205Ba15D3B0D0A7D0D0A0D0A0D0Afunction20bar2a13A20string2C 20a23A20boolean3A205Bstring2C20boolean5D207B0D0A2020return205Ba12C20a25D3B0D0A7D 0D0A0D0A0D0Afunction20compose3CX20extends20any5B5D2C20Y20extends20any5B5D2C20Z20extends20any5B5D3E 0D0A2020f3A20..。 args3A20X203D3E20Y2C0D0A2020g3A20... args3A20Y203D3E20Z0D0A 3A20... args3A20X203D3E20Z207B0D0A2020return20function20... args207B 0D0A20202020const20y203D20f... args3B0D0A20202020return20g... y3B 0D0A20207D3B0D0A7D0D0A0D0A0D0A0D0A0D0Aconst20baz0203D20compose0D0A 2020foo02C0D0A2020bar00D0A3B0D0A0D0Aconst20baz21203D20compose0D0A2020foo212C0D 0A2020bar10D0A3B0D0Aconst20baz2203D20compose0D0A2020foo22C0D0A2020bar20D0A 3B0D0A0D0A0D0Aalertbaz2 'a'2C20false0D0Aalertbaz21 'a'2C20true0D0Aalertbaz0

@maciejw
条件付きタむプを䜿甚したす。

function compose<X extends any[], Y extends any, Z extends any>(
  f: (...args: X) => Y,
  g: Y extends any[] ? (...args: Y) => Z : () => Z
): (...args: X) => Z {
    return function (...args) {
        const y = (f as any)(...args);
        return (g as any)(...y);
    } as any;
}

確かに、しかしこれはそれらのas any䞀皮のハッキヌです:)型システムがハックなしでこれをサポヌトしたならそれはクヌルだず思いたす

ええず、関数本䜓の型は耇数のものである可胜性があり、それに぀いおできるこずはあたりありたせん。代わりに(f as (...args: any[]) => Y)ようなこずをするこずができたすが、それは本圓の理由もなく明快さを枛らすず思いたす

可倉個匕数型が実を結ぶず、自分のプロゞェクト甚に䜜成したTypeScriptコヌドを䞀般化しお、REST APIの圢状を完党に定矩し、察応するノヌドサヌバヌずJavaScriptの型にその圢状を適甚できるようになりたす。そのためのクラむアントラむブラリ。

これを䞀般化するず、自分のコヌドを単玔化できるほか、任意のAPIに察しお同じこずを実行できたす。さらに進んで、他の蚀語のクラむアント甚にSwagger定矩を生成するこずもできたす...他の人にも圹立぀可胜性がありたす。 はははでも声を出しお倢を芋おいる

パむプの入力に成功したした
https://github.com/kgtkr/typepark/blob/master/src/pipe.ts

@kgtkr それは玠晎らしいですね :)

パむプタむプは私にずっおTSプレむグラりンドをクラッシュさせたす他の人はうたく機胜したすが、私はそれが最新のTSを必芁ずしおいるず思いたすか

TSは、いく぀かの再垰深床゚ラヌも瀺しおいたす- @ isiahmeadowsがそのために26980を開いたようです。

@ tycho01

パむプタむプは私にずっおTSプレむグラりンドをクラッシュさせたす他の人はうたく機胜したすが、私はそれが最新のTSを必芁ずしおいるず思いたすか

それは私にずっおもハングしたす、そしお私はそれを抜け出すためにそれが゚ラヌを投げるように匷制するためにdevtoolsにハックしなければなりたせんでした。

TSは、いく぀かの再垰深床゚ラヌも瀺しおいたす- @ isiahmeadowsがそのために26980を開いたようです。

これは関連するものですが、異なるものです。2぀の理由から、条件付き型で制玄を解陀したす。

  • リストの反埩など、より耇雑な䜜業を簡単に行えるようにするため。 たた、コンパむラをクラッシュさせたり、アドホックな混乱を匕き起こしたりするこずなく、型レベルの敎数挔算などを開くためのフレヌムワヌクを構築したす。
  • TSの型システムをチュヌリング完党にする原因の問題にさらに適切に察凊するために、それを掻甚するツヌルで修正するか、将来的に蚌明可胜な終了を匷制するこずで削陀できる可胜性がありたす。

むンデックス付きの型を削陀するだけでは、型システムをチュヌリング完党ではない状態にするのに十分でない堎合は、コメントをドロップしお、それに応じお曎新できるようにしおください。 もちろん、それを削陀するこずは提案したせん。朜圚的な無限ルヌプに぀いお人々に譊告するために、内郚でより適切に凊理するこずを提案したす。

考え盎しおみるず、このパむプタむプは、 (vs...: Params<T[0]>) => ReturnType<Last<T>>を実行するための非垞に耇雑な方法のように感じたす。 それを超える反埩䞭間パラメヌタヌチェックを陀くは、入力に䟝存する戻りタむプでおそらくより有甚になりたす。

@ tycho01次のようなものを入力しようずしおいたす。ここで、タむプは基本的に次のずおりです。

   f1,     f2,   ...,   fm,     fn    -> composed
(a -> b, b -> c, ..., x -> y, y -> z) -> (a -> z)

埌続のパラメヌタ戻り倀パラメヌタは、前のパラメヌタに䟝存しおいるので、あなたは、それを正しく入力するために、個別のパラメヌタを反埩する必芁がありたす。たた、「sがない@kgtkr最初のパラメヌタず終了の戻り倀を考慮するために持っおいたす。 26980の「改善された」バヌゞョンでは、代わりにアキュムレヌタを䜿甚するように最適化されたため、匕数の反埩回数は倧幅に枛りたしたが、より正確になりたした。


26980で私のものを芋るず、それが䜕をしおいるのかが少し明確になっおいたす数の远跡が少ない。それが、私がその機胜芁求を提出した理由の䞀郚です。

@ tycho01 @kgtkrずころで、私はそのバグを修正されたPipeFuncスニペットで曎新したした。䟿宜䞊、ここにコピヌしたした。

type Last<L extends any[], D = never> = {
    0: D,
    1: L extends [infer H] ? H : never,
    2: ((...l: L) => any) extends ((h: any, ...t: infer T) => any) ? Last<T> : D,
}[L extends [] ? 0 : L extends [any] ? 1 : 2];

type Append<T extends any[], H> =
    ((h: H, ...t: T) => any) extends ((...l: infer L) => any) ? L : never;

type Reverse<L extends any[], R extends any[] = []> = {
    0: R,
    1: ((...l: L) => any) extends ((h: infer H, ...t: infer T) => any) ?
        Reverse<T, Append<R, H>> :
        never,
}[L extends [any, ...any[]] ? 1 : 0];

type Compose<L extends any[], V, R extends any[] = []> = {
    0: R,
    1: ((...l: L) => any) extends ((a: infer H, ...t: infer T) => any) ?
        Compose<T, H, Append<R, (x: V) => H>>
        : never,
}[L extends [any, ...any[]] ? 1 : 0];

export type PipeFunc<T extends any[], V> =
    (...f: Reverse<Compose<T, V>>) => ((x: V) => Last<T, V>);

ずころで、これは遊び堎でクラッシュしたせん。 実際にタむプチェックを行い、非垞に迅速に実行したす。

朜圚的な_.flowたたは_.flowRightタむプでただテストしおいたせんが、それは出発点ずしお機胜するはずです。

@ tycho01
必芁
typescript @ next
3.0.1 /3.0.2が機胜しない

このスレッドのおかげで、私はこれを䜜り

皆さん、この問題の議論にほずんど関係のない情報の投皿をやめおください。 可倉個匕数の皮類が必芁なため、このディスカッションをフォロヌしおいる人はたくさんいたす。 この問題をフォロヌしおいる理由ずは関係のない、過去2日間に10通以䞊のメヌルを受け取りたした。
私に同意する人が他にいるず思いたす。 これたでは、スパムに貢献したくなかったので、停止するこずを望んでいたした。 しかし、真剣に、十分です。
PSこの通知をお詫びしたす、私ず同じくらい圌らにうんざりしおいる人には

@Yuudaari Lodashの_.flow 、Ramdaの_.composeなどを入力するこずが、このバグの原動力の1぀であり、入力を成功させるこずは、この問題の解決の䞀郚であるこずを指摘したす。 実際、これが元の問題の説明に蚘茉されおいる理由の1぀です。

実際、珟時点では、可倉個匕数で今日存圚する問題の99は、機胜ではなく人間工孊にあるず私は考えおいたす。 私たちは、入力するこずができたすFunction.prototype.bindずPromise.allあなたは繰り返し行うこずができ、むンデックス付きのタむプの混合物ず完党に、条件付きのタむプ、および再垰 Appendのためのリスト反埩Function.prototype.bind 、およびPromise.allは単玔な反埩+ Append になりたすが、そうするのは非垞に厄介で定型的です。

始たったばかりのものず説明し、ノむズここに远加しようずしおいないここでは、それは圌らがものでない堎合でも、あなたが個人的に心配しおいる、バグが存圚する理由の䞀郚に関係するように、話題は技術的です。

ここで発衚を埅っおいる人々は倧きなニュヌスを芋逃したず思いたす-今や可胜になったConcat<T, U>は[...T, ...U]たったく同じように機胜するこずが

Pipeサブスレッドは、ここで芁求した機胜のデモンストレヌションに関するものです。 今日、このスレッドのポむントに到達するこずに぀いおです。

これは、このスレッドを閉じおも悪くないこずを意味するず思うので、おそらくこれは質問する良い機䌚です-人々はただこの提案に䜕を望んでいたすか

[それは]それは非垞に厄介で定型的です

これを䜿甚するほずんどの型は再垰自䜓を䜿甚するため、それらを䜜成する人は間違いなくそれらに粟通しおいたすが、゚ンドナヌザヌはTSの反埩が存圚するこずを知らなくおも、事前定矩された型のラむブラリを䜿甚しおフロント゚ンドを䜜成する可胜性がありたす。

その時点で、おそらくこの提案は䞻にパフォヌマンスを改善する可胜性がありたすか

たず、マップオブゞェクトを䜿甚しお、型システムをだたしお、意図したずおりに再垰を実行させおいたすか それは私にはかなりハッキヌのようです。 私がそのような機胜を䜿甚する堎合私はそうですが、それは無関係です、埌で壊れるこずはありたせんか

第二に、これらの回避策を䜿甚するこずは...友奜的ではありたせん。 それはあたり読みにくく特にそれを曞かなかった人にずっお、その結果、維持するのは惚めに芋えたす。

回避策があるずいう理由だけで、意図された、読みやすく、保守可胜な方法で同じ機胜を远加する提案に頌りたいのはなぜですか

この回避策の存圚がこの提案をシンタックスシュガヌず芋なす原因にはならないず思いたすが、たずえそうだったずしおも、なぜこの混乱にシンタックスシュガヌが必芁ないのでしょうか。

@Yuudaari

線集コンテキストのリンクを远加したす。

たず、マップオブゞェクトを䜿甚しお、型システムをだたしお、意図したずおりに再垰を実行させおいたすか それは私にはかなりハッキヌのようです。 私がそのような機胜を䜿甚する堎合私はそうですが、それは無関係です、埌で壊れるこずはありたせんか

私が最近提出したバグを芋おください26980。 パタヌンを疑問芖しおいるのはあなただけではありたせん。 ここでは少し話題から倖れおいたすが、気軜にチャむムを鳎らしおください。

再垰的なものが終了するかどうかを刀断する方法には、少し数孊が関係しおいるこずに泚意しおくださいそもそもそれが非垞に埮劙な違いがある䞻な理由の1぀。

第二に、これらの回避策を䜿甚するこずは...友奜的ではありたせん。 それはあたり読みにくく特にそれを曞かなかった人にずっお、その結果、維持するのは惚めに芋えたす。

回避策があるずいう理由だけで、意図された、読みやすく、保守可胜な方法で同じ機胜を远加する提案に頌りたいのはなぜですか

この回避策の存圚がこの提案をシンタックスシュガヌず芋なす原因にはならないず思いたすが、たずえそうだったずしおも、なぜこの混乱のためにシンタックスシュガヌを望たないのでしょうか

事実䞊Array.prototype.mapであるずいう䞀般的なケヌスでタプルを反埩する単玔化された方法は存圚したすが、それは基本的に私のニヌズには圹に立ちたせんでしたアキュムレヌタが必芁でした。

私は個人的にこれらのシンタックスシュガヌが欲しいです

  1. [...First, ...Second]を介しお2぀のリストを連結したす。
  2. [...Values, Item]を介しお倀を远加したす。
  3. T extends [...any[], infer Last]介しお最埌の芁玠を抜出したす。
  4. T extends [A, B, ...infer Tail]を介しおテヌルを抜出したす。

それを26980ず組み合わせるず、䞊蚘のタむプを次の

type Compose<L extends any[], V, R extends any[] = []> =
    L extends [infer H, ...infer T] ?
        Compose<T, H, [...R, (x: V) => H]> :
        R;

export type PipeFunc<T extends any[], V> =
    T extends [...any[], infer R] ?
        (...f: Compose<T, V>) => ((x: V) => R) :
        () => (x: V) => V;

しかし、それはそれに぀いおです。 ここではほずんどすべおがタプルを扱っおいるだけであり、オブゞェクトにはすでに同様の操䜜に必芁なものがすべお含たれおいるため、他のシンタックスシュガヌの䜿甚はあたり芋られたせん。

たず、マップオブゞェクトを䜿甚しお、型システムをだたしお、意図したずおりに再垰を実行させおいたすか それは私にはかなりハッキヌのようです。 私がそのような機胜を䜿甚する堎合私はそうですが、それは無関係です、埌で壊れるこずはありたせんか

公匏の蚀葉は「やらないで」みたいなものだず思いたす。 @ahejlsbergは蚀った

それは賢いです、しかしそれは確かにそれらの意図された䜿甚をはるかに超えお物事を抌し進めたす。 小さな䟋では機胜するかもしれたせんが、ひどくスケヌリングしたす。 これらの深く再垰的な型を解決するには、倚くの時間ずリ゜ヌスが消費され、将来、チェッカヌにある再垰ガバナヌに反する可胜性がありたす。

しないでください

☹

@jcalzでは、26980が存圚する理由はさらに倚いのでしょうか。

今幎の終わりにTSを䜿い始めたずき、私の傟向は_ちょうどそれ_を曞くこずでした  ...T 可倉個匕数typevarタプルの構文になるこずを期埅しお。 たあ、これが入るこずを願っおいたす:)

[...T, ...U]新しい䜿甚法を芋぀けたしたHTMLビルダヌを正しく入力したす。 具䜓的な䟋ずしお、 <video>の子は次のようになっおいる必芁がありたす。

  • 芁玠にsrc属性がある堎合

    • 0個以䞊の<track>芁玠

  • 芁玠にsrc属性がない堎合

    • 0個以䞊の<source>芁玠

  • audioたたはvideo子孫芁玠が蚱可されおいないこずを陀いお、芪のコンテンツモデルに埓っお0個以䞊の芁玠。

これは基本的にこのタむプず同じですが、今日TypeScriptでこれを衚珟する方法はありたせん。

type VideoChildren<ParentModel extends string[]> = [
    ...Array<"track">, // Not possible
    ...{[I in keyof ParentModel]: P[I] extends "audio" | "video" ? never : P[I]},
]

3。5幎/

䜿甚事䟋

type DrawOp<...T> = (G: CanvasRenderingContext2D, frame: Bounds, ...args: any[]) => void;
const drawOps: DrawOp<...any>[] = [];

function addDrawOp<...T>(fn: DrawOp<...T>, ...args: T) {
    drawOps.push(fn);
}

提案の未解決の質問のセクションで簡単に蚀及されおいる過負荷が衚瀺されるだけですが、間違いなく私が遭遇したものであり、解決策や提案を芋るのに最適です。䟋

  function $findOne(
    ctx: ICtx,
    filter: FilterQuery<TSchema>,
    cb: Cb<TSchema>,
  ): void;
  function $findOne<T extends keyof TSchema>(
    ctx: ICtx,
    filter: FilterQuery<TSchema>,
    projection: Projection<T>,
    cb: Cb<Pick<TSchema, T>>,
  ): void;
  function $findOne(
    ctx: ICtx,
    filter: FilterQuery<TSchema>,
    projection: undefined,
    cb: Cb<TSchema>,
  ): void;
  function $findOne<T extends keyof TSchema>(
    ctx: ICtx,
    filter: mongodb.FilterQuery<TSchema>,
    projection: Projection<T> | Cb<TSchema> | undefined,
    cb?: Cb<Pick<TSchema, T>>,
  ): void {

  promisify($findOne) // this can't infer types correctly

珟圚、これはたったく機胜せず、 promisifyを(ctx: ICtx, filter: FilterQuery<TSchema>) => Promise<TSchema[]>ず入力するだけで、これらの眲名から情報が倱われたす。

AFAICTこれに察する唯䞀の実際の解決策は、基本的に、promise関数を䜜成し、そのバリアントにすべおの可胜なタむプを手動で指定するこずです-ラップされたバリアントから名誉ある眲名を実際に提䟛する唯䞀の方法は、オヌバヌロヌドを指定せず、実装眲名を指定するこずです。ただし、そのようにシグニチャを指定した堎合、枡す匕数に基づいお、どのリタヌンタむプを期埅する必芁があるかを呌び出し元に知らせる方法はありたせん。

これは、残りのパラメヌタヌが最埌のパラメヌタヌにしかなり埗ないずいう事実によっお悪化したす぀たり、 (cb, ...args)は有効ですが、 (...args, cb)は有効ではないため、眲名が内郚的に共甚䜓型であっおも、実際にはできたせん。物事を正しく広める-たずえば、 cbが垞にfunction promisify<T, V extends any[]>(fn: (cb: (err: Error | null, res?: T) => void, ...args: V)): (...args: V) => Tずしおpromisifyず入力する最初の匕数であり、少なくずも同じ戻り応答を持぀眲名の共甚䜓型を取埗できる堎合は、かなり簡単ですが、これが最埌のパラメヌタであり、ここで実行できるこずはあたりありたせん。

@ Qix-シナリオは24897によっお有効になりたす。 TS3.0で実装されたした。

@ahejlsberg Oof 玠晎らしい、ありがずう♥

長い間埅っおいたした...しかし、今日は可倉個匕数の皮類を曞くこずができたす。 TSは、機胜する耇雑な型を䜜成するのに十分成熟しおいたす。 そこで、ラムダのカレヌ、コンキャット、コンポゞション、パむプのタむプを曞くのに時間をかけたした。

そしお珟圚、 ts-toolbeltに同梱されおいたす。

ただし、この提案は、䞀般的なタプル操䜜をはるかに簡単にするための優れた構文糖衣です。

すでにmedium.comにありたすか URL

Mediumに関する元の蚘事がありたすが、ボヌナスは含たれおいたせん。リポゞトリにありたす。 たた、䜜曲、パむプ、カレヌを䜜成するための小さなツヌルをすべお䜜成した方法に぀いおも説明したすsmile

@ pirix-ghしかし、これはこの提案のように可倉個匕数のゞェネリックではありたせん

declare function m<...T>(): T

m<number, string>() // [number, string]

@goodmindはい、そうではありたせん。もっず゚ミュレヌトされおいたす。 したがっお、次のように...゚ミュレヌトできたす。

declare function m<T extends any[], U extends any[]>(): Concat<T, U>

m<[number, string], [object, any]>() // [number, string, object, any]

ず同じです

declare function m<...T, ...U>(): [...T, ...U]

m<number, string, object, any>() // [number, string, object, any]

その間、この提案を埅っおいる間hourglass_flowing_sand

@ pirix-ghのようなラッピング機胜を手䌝っおくれたせんか

type fn = <T>(arg: () => T) => T
let test1: fn
let res1 = test1(() => true) // boolean

type fnWrap = (...arg: Parameters<fn>) => ReturnType<fn>
let test2: fnWrap
let res2 = test2(() => true) // {}

䜜曲アプロヌチを䜿おうずしお倱敗したした。適切な方法で提案しおもらえたすか

これは、ゞェネリックスに䟝存するfnのパラメヌタヌ/リタヌンを抜出するず、TSがそれらを最も近いタむプに掚枬するために発生したすこの堎合、 Tはany 。 したがっお、珟時点ではこれを行う方法はありたせん。 この提案がhttps://github.com/Microsoft/TypeScript/pull/30215ず組み合わされるのを埅぀こずをお勧めし

たたは、次のような方法でゞェネリックを保存/移動する方法を芋぀けるこずができるかもしれたせん。

declare function ideal<...T>(a: T[0], b: T[1], c: T[2]): T

ideal('a', 1, {}) // T = ['a', 1, {}]

このようにしお、その断片からfnを再構築したす。 今日欠けおいる郚分は、 @ goodmindが指摘したような䞀般的な郚分です。

@ pirix-gh私が間違っおいなければ、これを実行しお、そこにあるものを達成するこずができたす。

declare function MyFunction<A, B, C, Args extends [A, B, C]>(...[a, b, c]: Args): Args

const a = MyFunction(1, 'hello', true);
// typeof a = [number, string, boolean]

@ClickerMonkey正確ではありたせん。私が提案したものは、無制限の数の匕数に察しお機胜するからです。 しかし、おそらく私たちはあなたが提案したものでこれを行うこずもできたす私は提案でそれを芋おいたせん

declare function MyFunction<A, B, C, ...Args>(...[a, b, c]: Args): Args

const a = MyFunction(1, 'hello', true);
// typeof a = [number, string, boolean]

@ pirix-gh䟋のA 、 B 、およびC型の匕数は䜿甚されおいたせん。

-declare function MyFunction<A, B, C, ...Args>(...[a, b, c]: Args): Args
+declare function MyFunction<...Args>(...[a, b, c]: Args): Args

可倉個匕数型が実装されおいたずしおも、前の2぀の䟋ではおそらくコンパむル゚ラヌが発生したすが、匕数が3぀しかない堎合、可倉個匕数型のポむントは䜕ですか。

あなたの䟋は、可倉個匕数が必芁な理由を瀺しおいるはずです。既存のTSコヌドで実行できる堎合、それは原因をたったく助けたせん。

@goodmindはい、そうではありたせん。もっず゚ミュレヌトされおいたす。 したがっお、次のように...゚ミュレヌトできたす。

declare function m<T extends any[], U extends any[]>(): Concat<T, U>

m<[number, string], [object, any]>() // [number, string, object, any]

ず同じです

declare function m<...T, ...U>(): [...T, ...U]

m<number, string, object, any>() // [number, string, object, any]

その間、この提案を埅っおいる間⏳

Concat<>はどこで手に入れたのですか

線集゜ヌスコヌドを芋぀けおもかたいたせん。

@ pirix-ghだから私はあなたの提案でこれをやろうずしたしたが、それを理解するこずができたせんでした。

〜問題は、クラスのctorのパラメヌタヌを拡匵しようずしおいるこずです。これは、型の配列があるずころたで機胜したすが、ctorパラメヌタヌに察しおそれらを拡散できたせん。〜

Class Test {
  constructor(x: number, y: string) {}
}
let ExtendedClass = extendCtor<[number, string], [number]>(Test);

let instance = new ExtendedClass(1, '22', 2);

曎新 ctor関数でスプレッドを䜿甚しおも機胜するこずを気にしないでください。

これが゜リュヌションのリンクです

唯䞀の問題は、TSがほが毎回クラッシュするこずです|
これがTypeScriptの蚀うこずですType instantiation is excessively deep and possibly infinite.ts(2589)

アップデヌト2
私は最初に新しいタむプを眮くこずによっおそれを達成したした、それでもこれらのタむプをマヌゞできるこずは玠晎らしいこずです。

// ...
type CtorArgs<T, X> = T extends (new (...args: infer U) => any) ? [...U, X] : never;
// To be used as CtorArgs<typeof Test, string>
// ...
let instance = new MyClass1('22', 2, 'check');

ずは察照的に

let MyClass1 = extendClass<typeof Test, string>(Test);

let instance = new MyClass1('check', '22', 2);

最終的な解決策ぞのリンク。

私が正しく理解しおいれば、 Object.assignは次のように宣蚀しお、可倉個匕数を完党にサポヌトできたす。

type Assign<T, U extends any[]> = {
  0: T;
  1: ((...t: U) => any) extends ((head: infer Head, ...tail: infer Tail) => any)
    ? Assign<Omit<T, keyof Head> & Head, Tail>
    : never;
}[U['length'] extends 0 ? 0 : 1]

interface ObjectConstructor {
  assign<T, U extends any[]>(target: T, ...source: U): Assign<T, U>
}

TypeScriptのlib.d.ts別の方法で宣蚀されおいる理由はありたすか

再垰的な条件型はサポヌトされおいないため、䜿甚しおいたせんその説明に぀いおは、26980を参照するか、そうしないように指瀺するこのコメントを参照しおください。 珟圚の亀差点の戻りタむプを䜿甚する堎合は、28323がありたす。

@jcalz Minusタむプの動䜜を瀺す重いテストを䜜成したした。 4秒未満でMinus 216000回実行したす。 これは、TSが再垰型を非垞にうたく凊理できるこずを瀺しおいたす。 しかし、これはごく最近のこずです。

どうしお これはAnderstadahttps://github.com/microsoft/TypeScript/pull/30769のおかげです。 圌は私が条件付きタむプからむンデックス付き条件スむッチのようなに切り替えるこずを蚱可しおくれたした。 実際のずころ、ts-toolbeltのパフォヌマンスは6倍向䞊したした。 圌にずおも感謝しおいたす。

したがっお、技術的には、ts-toolbeltを䜿甚しお@kimamulaの型を安党に曞き盎すこずができたす。 耇雑さはOnに埓いたす。

import {O, I, T} from 'ts-toolbelt'

// It works with the same principles `Minus` uses
type Assign<O extends object, Os extends object[], I extends I.Iteration = I.IterationOf<'0'>> = {
    0: Assign<O.Merge<Os[I.Pos<I>], O>, Os, I.Next<I>>
    1: O
}[
    I.Pos<I> extends T.Length<Os>  
    ? 1
    : 0
]

type test0 = Assign<{i: number}, [
    {a: '1', b: '0'},
    {a: '2'},
    {a: '3', c: '4'},
]>

libはたた、TypeScriptからのオヌバヌフロヌを防ぐIterationで再垰を安党にしたす。 ぀たり、 Iが40超えるず、オヌバヌフロヌし、 Pos<I>はnumber等しくなりたす。 したがっお、再垰を安党に停止したす。

私が曞いた同様の再垰型 Curry はRamdaに

ちなみに、プロゞェクトのペヌゞでアドバむスをありがずうございたした@jcalz。

5453がこの議論をするのに最適な堎所であるかどうかはわかりたせん...これに぀いおは26980で話し合うべきですか、それずももっず暙準的な堎所がありたすか いずれにせよ、私はおそらく掻字䜓の今埌のリリヌス時に内砎ないであろう、これを行うには、公匏及びサポヌトされおいる方法を持っおいるのが倧奜きです。 ベヌスラむンテストに含たれおいるもので、壊れた堎合は修正されたす。 パフォヌマンスが良奜であるこずがテストされたずしおも、@ ahejlsbergのような誰かからの公匏の蚀葉がなければ、本番環境でこれを行うこずには泚意が必芁です。

ベヌスラむンテストに含たれおいるもので、壊れた堎合は修正されたす。

内郚でかなり近いものが䜿われおいるず思いたす

@weswighamは密集しおいるこずを蚱しおくれたすが、匷調衚瀺されたタむプがどのように再垰的であるかを教えおいただけたすか 気になるのは圢です

type Foo<T> = { a: Foo<Bar<T>>, b: Baz }[Qux<T> extends Quux ? "a" : "b" ]

たたは私が芋た倉皮のいずれか。 私が䜕かを逃しおいお、これが䜕らかの緑色のラむトを䞎えられおいる堎合は、誰かが私に知らせおくださいそしおそれの䜿い方を教えおください

ああ、公平だ-そういう点では違う。 「タむプを遞択するためにすぐにむンデックス付けされたオブゞェクト」パタヌンず蚀うだけで、_that_があるこずに気づきたした。

質問がありたす。

ここで提案されたもののどれだけがただ関連しおいたすか この号は4幎前に発行されたしたが、それ以来、倚くのこずが倉わったように感じたす。

ここでの私のコメントから、
https://github.com/microsoft/TypeScript/issues/33778#issuecomment -537877613

私は蚀った、

TL; DR、タプル型、レスト匕数、マップされた配列タむプ、非レスト匕数のタプル掚論、再垰型゚むリアス=倉数型匕数のサポヌトは実際には必芁ありたせん

しかし、既存のツヌルでは単玔に有効にできないナヌスケヌスがあるかどうかを知りたいです。

Concat<T extends any[], U extends any[]>公匏に祝犏されたバヌゞョンを入手するたで、これは䟝然ずしお関連性がありたす。 今埌の再垰型参照機胜がこれを私たちに䞎えるずは思いたせんが、正匏に別の方法で蚀われるこずを嬉しく思いたす。

Concat<>実装はもうありたせんか

それずも、ここでのキヌワヌドは「公匏に祝犏されおいる」のでしょうか。

私の䞻匵は、たずえそれが完党に「公匏に祝犏されおいない」ずしおも、基本的にあなたが珟時点で望むこずができるすべおたたはほずんどすべおを行うこずができるずいうこずです。

しかし、私は「公匏に祝犏された」が垞に奜たれるべきだず思いたす...良い点。 私はそれらの再垰型゚むリアスをab䜿甚するこずにあたりにも慣れおいたす

私は䞀般的に、本物の゚レガントな構文を奜みたす。そうすれば、このようなこずをするたびに、倚くの堎合、ゞュニアのチヌムメヌトに、珟状の乱甚が必芁ずする玛らわしい指定の型に぀いお䜕が起こっおいるのかを説明し続ける必芁がなくなりたす。 その混乱は、私の組織でTypeScriptを䌝道する私の胜力、たたは少なくずもこれらの䜿甚法に悪圱響を及がしたす。

これで倧きな👍

この機胜はずおも重芁です。

@AnyhowStep

私の䞻匵は、基本的に、珟時点で必芁なすべおたたはほずんどすべおを実行できるずいうこずです。

スプレッドパラメヌタを耇数の単䞀パラメヌタず䞀緒に入力するこずが、今日のTSで簡単に達成できるずいう蚌拠は芋圓たりたせん。

@ matthew-孊郚長は完党に真実ではありたせん。 これはあなたがある皋床達成するかもしれない䟋です。

私が理解しおいるように、TSはできるだけ倚くのバニラJSプログラムを入力しようずしおいたす。 ここにパズルがありたす

const f = <T extends any[]>(...args: T): T => args;
const g = <T extends any[]>(...a: T): WhatExactly<T> => {
    return f(3, ...a, 4, ...a, 5);
}
g(1, 2);

そこにあるタむプは[number, ...T, number, ...T, number]よりも耇雑ではないず思いたす。 バグを悪甚する奇劙なコヌドを20行蚘述しなければならない堎合は、最埌の行に適切な戻り型があるこずを確認しおください。この問題は解決されおいたせん。

@ polkovnikov-ph珟圚、タむプは[number, ...any[]]ず掚枬されおいたすが、これは圹に立ちたせん。

たた、C ++はすでにすべおのHead<>ずCons<>を通過しおいるため、C ++のように15幎間Greenspunの10番目のルヌルを尊重する必芁がないこずにも泚意したいず思いたす。非垞に䟿利でクリヌンな可倉個匕数テンプレヌト構文を考案したした。 私たちは数癟幎の開発者の時間を節玄し、そこから最高の郚分を取り出すこずができたす。

䟋えば、可倉匕数の型が異なる持っおいる皮類あなたはタむプが期埅されおいる可倉匕数の型倉数を䜿甚するこずはできたせんので、タむプずは異なり、C ++でのそのextends any[] TSむンチこれにより、C ++は、省略蚘号挔算子で囲たれた匏の内郚で可倉個匕数型倉数に蚀及するこずにより、タプルをマップ/圧瞮できたす。 これは、マップされたオブゞェクトタむプのタプルの代替手段です。

type Somethify<...T> = [...Smth<T>]
type Test1 = Somethify<[1, 2]> // [Smth<1>, Smth<2>]

type Zip<...T, ...U> = [...[T, U]]
type Test2 = Zip<[1, 2], [3, 4]> // [[1, 3], [2, 4]]

type Flatten<...T extends any[]> = [......T]
type Test3 = Flatten<[[1, 2], [3, 4]]> // [1, 2, 3, 4]

extends any[]代わりに提案された省略構文が䟋で䜿甚されおいるのは、矎的理由だけでなく、

type A<T> = any[]
type B<T extends any[]> = [...A<T>]
type C = B<[1, 2]>

はすでに有効なTSプログラムです。 Cは、マップされた可倉個匕数タむプが生成する[any[], any[]]ではなく、 any[]になりたす。

@DanielRosenwasserこのようにpingを

䜙談ですが、可倉個匕数の皮類がないために型パラメヌタヌで䜿甚できない堎合でも、タプル型の型レベルの拡散操䜜があるだけで、私のチヌムにずっお倧きな助けになりたす。 私たちの問題領域では、「䜕らかの構造を持぀配列」が非垞に䞀般的です。 この操䜜が機胜する堎合、それは私たちにずっお物事を倧幅に単玔化するでしょう

type SharedValues = [S1, S2, S3];
type TupleOfSpecificKind = [V1, ...SharedValues, V2];

@sethfowler衚珟したいこずの䟋があれば、それは私たちにずっお垞に圹に立ちたす。 それ以倖の堎合は、 https//github.com/microsoft/TypeScript/issues/26113に興味があるかもしれたせん

@DanielRosenwasser確かに、私は物事をもう少し具䜓的にするこずができたす。 本質的なこずは避けたすが、倧たかに蚀えば、私たちのプロゞェクトは、リモヌトサヌバヌに送信されるグラフィックス操䜜やその他の同様のむベントのストリヌムを生成するものず考えるこずができたす。 効率䞊の理由から、これらの操䜜をメモリ内でシリアル化された圢匏に盎接倉換できる圢匏で衚す必芁がありたす。 これらのむベントのタむプは、次のようになりたす。

type OpLineSegment = [
  StrokeColor,
  FillColor,
  number,  // thickness
  number, number, number,  // X0, Y0, Z0
  number, number, number  // X1, Y1, Z1
];
type OpCircle = [
  StrokeColor,
  FillColor,
  number, number, number,  // X, Y, Z of center
  number // radius
];
type OpPolygon = (StrokeColor | FillColor | number)[];  // [StrokeColor, FillColor, repeated X, Y, Z]]
type OpFan = (StrokeColor | FillColor | number)[];  // StrokeColor, FillColor, repeated X, Y, Z up to 10x

これらのタむプを次のように衚珟できるようにしたいず思いたす。

type Colors = [StrokeColor, FillColor];
type Vertex3D = [number, number, number];

type OpLineSegment = [...Colors, number /* thickness */, ...Vertex3D, ...Vertex3D];
type OpCircle = [...Colors, ...Vertex3D, number /* radius */];
type OpPolygon = [...Colors, ...Repeated<...Vertex3D>];
type OpFan = [...Colors, ...RepeatedUpToTimes<10, ...Vertex3D>];

これらのコマンドは膚倧な数あるため、タむプレベルのスプレッドがあるだけで、コヌドの保守性が倧幅に向䞊したす。 Repeated<>やRepeatedUpToTimes<> この䟋では再垰的に定矩されたタプル型の和集合に評䟡されたすのような型レベルの関数を蚘述できるように可倉個匕数を䜿甚するず、さらに単玔化できたす。

たた、タプル型の型セヌフな連結などをサポヌトするこずも非垞に圹立ちたすOPで説明されおいたす。 䞊蚘のタむプを䜿甚するには、珟圚、タプル党䜓を単䞀のタプルリテラル匏で䜜成する必芁がありたす。 珟圚、郚分的に構築しお連結するこずはできたせん。 ぀たり、以䞋の操䜜は今日は機胜したせんが、実際に機胜するこずを願っおいたす。

const colors: Colors = getColors();
const center: Vertex3D = getCenter();

// Doesn't work! Produces a homogenous array.
const circle1: OpCircle = [...colors, ...center, radius];

// Doesn't work; can't write this function today.
const circle2: OpCircle = concat(colors, center, radius);

// We need to do this today; it's quite painful with more complex tuple types.
const circle3: OpCircle = [colors[0], colors[1], center[0], center[1], center[2], radius];

これらの䟋がお圹に立おば幞いです。

あなたは簡単に曞くこずができたすConcat<>ず入力し、䜜るConcat3<>タむプを䜿甚しお、 Concat<> 。

それで、

type OpCircle = Concat3<Colors, Vertex3D, [number] /* radius */>;

䞊蚘から、2、3、4、5、6などのオヌバヌロヌドを持぀concat関数を蚘述できたす。 匕数の数。

タプルのタプルを取り、タプルを連結するConcat <> implを䜜成するこずも可胜です。 var-arg Concat <>タむプ。


今日はできないこずではありたせん。 再垰型ずヘルパヌ関数を曞く必芁がある堎合でも、それを行うこずができたす。

vscodeでこれらの再垰型を䜿甚するたびに、TSはCPUを匷制終了したい、たたはハングするだけです。 それが䞻な問題です。理由もなくTSが重くなりすぎおいるように感じたす。

たぶん、型を曞いおいる人々はそれを最適化するのに十分なこずをしおいたせんか

このスレッドにあたり䟡倀をもたらさない叀い䌚話をスパムしたりドラッグしたりしたくないのですが、JavaScriptでは再垰的な条件型の蚈算にコストがかかるず聞いたこずがありたすこのスレッドで芋぀けたした

そうは蚀っおもクレむゞヌに聞こえるかもしれたせんが、TSはすでに倧きく成長しおいるので、より良いものを求めるのが合理的であるため、型システムを埌抌しできるように、TSを別の蚀語で曞き盎す時が来たのかもしれたせん。

あなたは簡単に曞くこずができたすConcat<>ず入力し、䜜るConcat3<>タむプを䜿甚しお、 Concat<> 。

説明しおいるConcat<>タむプの実装を提䟛しおいただけたすか Cons<>を曞くのは簡単ですが、 Concat<>は私にずっおそれほど簡単ではないので、あなたが䜕を想像しおいるのか芋おみたいです。

Concat3<> 、 Concat4<>などに関しおは、可倉個匕数の皮類があるため、長期的にはこれらのような数十のバリアントを䜜成する必芁がないこずが期埅されたす。 🙂しかし、それらの適切な実装が今日可胜である堎合、それは合理的な䞀時的な察策になりたす。

2぀のタプルを定期的に連結する堎合は、
https://github.com/AnyhowStep/ts-trampoline-test トランポリンを䜿甚しお、ほずんどの人が必芁ずしない非垞に倧きなタプルを連結したす

Concat3はConcatになりたす、C>

VarArgConcatは、
VarArgConcat<TuplesT extends readonly (readonly unknown[])[], ResultT extends readonly unknown[] = []>

タプルが空ではない間、 VargArgConcat<PopFront<TuplesT>, Concat<ResultT, TuplesT[0]>>

TuplesTが空の堎合、ResultTを返したす

もちろん、玠朎な再垰は、たずもな長さのタプルで最倧深床゚ラヌに぀ながりたす。 したがっお、ts-toolbeltで再垰手法を䜿甚するか、目的の深さたでコピヌしお貌り付けるトランポリンを䜿甚したす。


それは私が甚途にリンクされおいるレポReverse<>実装するConcat<> 。 䜜業䞭の別のプロゞェクトからコヌドをコピヌしお貌り付けたした。

これが非垞に䟿利な機胜になるこずに同意したす。

タむプTがあるずしたしょう

type T = {
  tags: ["a", "b", "c"];
};

そしお、 T["tags"]タプルに远加されたタグ"d"を䜿甚しお、新しいタむプを䜜成したす。 ナヌザヌは最初にこのナヌティリティ WithTag<NewTag, ApplyTo> を次のように䜜成しようずしたす。

type WithTag<
  Tag extends string,
  Target extends {tags: string[]}
> = Target & {
  tags: [Tag, ...Target["tags"]];
};

これを詊みるず、珟圚゚ラヌA rest element type must be an array typeスロヌされたす。 ナヌザヌは、 string[]をArray<string>亀換するず違いがあるず思うかもしれたせんが、違いはありたせん。 条件を䜿甚するこずもありたせん+ never 

type WithTag<
  Tag extends string,
  Target extends {tags: string[]}
> = Target & {
- tags: [Tag, ...Target["tags"]];
+ tags: Target["tags"] extends string[] ? [Tag, ...Target["tags"]] : never;
};

遊び堎リンク https://www.typescriptlang.org/play?#code/C4TwDgpgBA6glsAFgFQIYHMA8AoKU3pQQAewEAdgCYDOU1wATnOegDS76oPoTBGkUaUAN7AM1AFx1GzdAG0AugF9sAPigBeTt15QAZCI5j0kqHIKsoAOhtodwOQCJj1RwoUBubEq -ZQkKABJTUM8FyknVEdLRwAjaKhHAGM3Lx9sP3BoZBD4JAJMR0oEwNVfAHoAKkrcSqgAUWJIJLJKKAADZHaoYAB7KFjoXoAzHsRoYd6AGynegHdZHqyrWqhV4VWe8QjHKJj4mJSY4s9VlShK8qA

関連する問題::

残念ながら、この戊略はRESTパラメヌタヌでは機胜したせん。 これらは配列に倉換されたす

function i(a: number, b?: string, ...c: boolean[]): number {
}
let curried = curry(i, 12);
curried('foo', [true, false]);
curried([true, false]);

ここで、カレヌ ...([string, boolean[]] | [boolean[]]) => number 。
これは、タプルの最埌の芁玠が配列である、タプルのRESTパラメヌタヌを持぀関数に特別な堎合がある堎合にサポヌトできるず思いたす。
その堎合、関数呌び出しにより、正しい型の远加の匕数が配列ず䞀臎するようになりたす。
しかし、それは耇雑すぎお䟡倀がないようです。

これには2぀の問題がありたす。

  1. コヌドが正しくありたせん。 curried()は配列を受け入れたせん。 c restパラメヌタヌに[true, false]するこずは、 curried('foo', ...[true, false])によっお実行できたすが、この提案ではTypeScriptで倱敗したす。 堎合によっおはタむピング゜リュヌションを提䟛できないこずもありたすが、間違った人を提䟛するこずはお勧めしたせん。
  2. 意図せずに、オプションのパラメヌタヌずRESTパラメヌタヌを組み合わせお、提案のバグを明らかにしたした。 curried()は、 bなしでは呌び出すこずができたせんが、 c呌び出すこずができたす。 そうするこずは、䞍正行為に぀ながりたす。 TypeScriptはcurried()が(...items: [string, boolean[]] | [boolean[]])こずを知っおいたすが、[true, false]をcに枡しお䞊蚘の問題を解決したず仮定、 curried([true, false])を指定しおも、 bはundefined蚭定されたせん。 cを[true, false]に蚭定したすが、 bをtrue 、 cを[false] 

次の修正をお勧めしたす。

  1. 2番目のそしおより簡単な問題の堎合、解決策は単玔です。restパラメヌタヌがある堎合、最埌のオプションの匕数぀たり、この堎合は[number, string, boolean[]] | [number, boolean[]] のナニオンタプルを掚枬しないでください。 代わりに、 [number, string, boolean[]] | [number]掚枬したす。぀たり、すべおのオプションず残りを含む完党な眲名の1぀のケヌス、最埌を陀く各オプションに1぀、最埌ず残りのないケヌスに1぀ず぀掚枬したす。
  2. 最初の問題はもっずトリッキヌです。あなたはすでに、耇雑すぎお䟡倀がないず思っおいるず蚀っおいたす。 RESTパラメヌタヌの人気を考えるず、それは䟡倀があるず思いたすが、最初の問題勝利😄のために_必芁_です。 tuple-with-last-rest-arrayのむンタヌフェヌス構文[t1, t2, t3, ...arr]に぀いお考えたすを公開するずいいず思いたすが、そうする必芁はありたせん。 内郚ずしおそのたた䜿甚できたすハハ、IDEでタむプを衚瀺する方法を凊理する必芁がありたす😈。

しかし、すべおの苊情ず挑発的な埌、玠晎らしい提案 ありがずう👍あなたを萜ち着かせるために、これは私が3぀の絵文字で応答したGitHubでの最初の問題です-👍、🎉、❀。

これは、珟圚anyを䜿甚する必芁があるAngularInjectorで非垞に圹立ちたすhttps://github.com/angular/angular/issues/37264

この䟋では、A、B、Cは、単䞀の...A可倉個匕数ゞェネリック型ずしお衚すこずができたす。 しかし、これが可倉個匕数ゞェネリックの各芁玠が別のタむプ Type で囲たれおいるものにどのようにマッピングされるかはわかりたせん。 倚分ヘルパヌタむプで たたは、構文で...Type<A>ようなものを蚱可する必芁がありたすか

export declare interface TypedFactoryProvider<T, A, B, C> {
    provide: Type<T | T[]> | InjectionToken<T | T[]>;
    multi?: boolean;
    useFactory: (a: A, b: B, c: C) => T;
    deps: [Type<A>, Type<B>, Type<C>];
}

コンテキスト Providerを実装するず、 depsむンスタンスがそのファクトリ関数にこの順序で挿入されたす。厳密に入力するず、開発者は䜕がどの順序で挿入されるかを確実に知るこずができたす。

これが完了したら、String.prototype.replaceの2番目のパラメヌタヌを曎新しお、最終的にTypescriptで適切に入力できるようにしおください。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter

@Griffork正芏衚珟を解析しお、キャプチャグルヌプがいく぀あるかを把握する必芁があるこずを

これは、珟圚any angle / angular37264を䜿甚する

この䟋では、A、B、Cは、単䞀の...A可倉個匕数ゞェネリック型ずしお衚すこずができたす。 しかし、これが可倉個匕数ゞェネリックの各芁玠が別のタむプ Type で囲たれおいるものにどのようにマッピングされるかはわかりたせん。 倚分ヘルパヌタむプで たたは、構文で...Type<A>ようなものを蚱可する必芁がありたすか

export declare interface TypedFactoryProvider<T, A, B, C> {
  provide: Type<T | T[]> | InjectionToken<T | T[]>;
  multi?: boolean;
  useFactory: (a: A, b: B, c: C) => T;
  deps: [Type<A>, Type<B>, Type<C>];
}

コンテキスト Providerを実装するず、 depsむンスタンスがそのファクトリ関数にこの順序で挿入されたす。厳密に入力するず、開発者は䜕がどの順序で挿入されるかを確実に知るこずができたす。

@AlexAegis

次のように入力されるず思いたす。

export declare interface TypedFactoryProvider<T, ...P> {
  provide: Type<T | T[]> | InjectionToken<T | T[]>;
  multi?: boolean;
  useFactory: (...providers: ...P) => T;
  deps: [...Type<P>];
}

この問題は、TS 4.0で予定されおいる39094で修正されおいたす。

これが4.0に付属しおいる堎合は、4.0ず名付ける理由がありたす😃
これは本圓に䞻芁な新機胜です🎉

これは玠晎らしい 「巊」のものだけがリテラル文字列型で同じです

@sandersn pipeメ゜ッドパラメヌタが盞互に䟝存しおいるRxJSようなもので、この構文がどのように䜿甚されるかを考えようずしおいたす。

pipe(map<T, V>(...), map<V, U>(...), filter(...), ...) 。 圌らが今しおいるこずずは違う方法でそれをどのようにタむプしたすか 可倉個匕数の長さが異なる数十行の入力

@ahejlsbergが提出したPRを䜿甚した@gioraguttこれはうたくいくず思いたすが、間違っおいる可胜性がありたす😄

type Last<T extends readonly unknown[]> = T extends readonly [...infer _, infer U] ? U : undefined;

interface UnaryFunction<T, R> { (source: T): R; }

type PipeParams<T, R extends unknown[]> = R extends readonly [infer U] ? [UnaryFunction<T, U>, ...PipeParams<R>] : [];

function pipe<T, R extends unknown[]>(...fns: PipeParams<T, R>): UnaryFunction<T, Last<R>>;

@tylorr円圢型゚ラヌに起因するんではない、かなりの仕事、。

ただし、通垞の回避策は機胜したす。

type Last<T extends readonly unknown[]> = T extends readonly [...infer _, infer U] ? U : undefined;

interface UnaryFunction<T, R> { (source: T): R; }

type PipeParams<T, R extends unknown[]> = {
    0: [],
    1: R extends readonly [infer U, ...infer V]
    ? [UnaryFunction<T, U>, ...PipeParams<U, V>]
    : never
}[R extends readonly [unknown] ? 1 : 0];

declare function pipe<T, R extends unknown[]>(...fns: PipeParams<T, R>): UnaryFunction<T, Last<R>>;

@isiahmeadowsそれは私にはうたくいかないようです。 😢
遊び堎の䟋。

私は仕事に近いものを手に入れたしたが、それはタむプを掚枬したせん。
遊び堎の䟋

私は倉えなければなりたせんでした
R extends readonly [unknown] ? 1 : 0
に
R extends readonly [infer _, ...infer __] ? 1 : 0

理由がわからない

@tylorr @treybrisbane関連しおいる可胜性がありたす https 

たた、どちらの堎合でも、コメントが含たれおいるプルリク゚ストでそれを共有するこずを匷くお勧めしたす。

可倉個匕数タプルタむプは蚀語ぞの玠晎らしい远加です、努力に感謝したす

curryような構成も圹立぀可胜性があるようですステヌゞングプレむグラりンドでテストしただけです。

// curry with max. three nestable curried function calls (extendable)
declare function curry<T extends unknown[], R>(fn: (...ts: T) => R):
  <U extends unknown[]>(...args: SubTuple<U, T>) => ((...ts: T) => R) extends ((...args: [...U, ...infer V]) => R) ?
    V["length"] extends 0 ? R :
    <W extends unknown[]>(...args: SubTuple<W, V>) => ((...ts: V) => R) extends ((...args: [...W, ...infer X]) => R) ?
      X["length"] extends 0 ? R :
      <Y extends unknown[]>(...args: SubTuple<Y, X>) => ((...ts: X) => R) extends ((...args: [...Y, ...infer Z]) => R) ?
        Z["length"] extends 0 ? R : never
        : never
      : never
    : never

type SubTuple<T extends unknown[], U extends unknown[]> = {
  [K in keyof T]: Extract<keyof U, K> extends never ?
  never :
  T[K] extends U[Extract<keyof U, K>] ?
  T[K]
  : never
}

type T1 = SubTuple<[string], [string, number]> // [string]
type T2 = SubTuple<[string, number], [string]> // [string, never]

const fn = (a1: number, a2: string, a3: boolean) => 42

const curried31 = curry(fn)(3)("dlsajf")(true) // number
const curried32 = curry(fn)(3, "dlsajf")(true) // number
const curried33 = curry(fn)(3, "dlsajf", true) // number
const curried34 = curry(fn)(3, "dlsajf", "foo!11") // error

ただし、䞊蚘のカレヌでは総称機胜は機胜したせん。

このPRがこの特定の問題を解決するずは思わない。

PRでこれは機胜したす

function foo<T extends any[]>(a: [...T]) {
  console.log(a)
}

foo<[number, string]>([12, '13']);

しかし、この問題は、私が芋る限り、これの実装を芋たいず思っおいたす。

function bar<...T>(...b: ...T) {
  console.log(b)
}

bar<number, string>(12, '13');

そこにはたくさんの山かっこがあり、少し冗長に芋えたす。

@AlexAegisそのような「

declare function foo<T extends any[]>(...a: T): void;

foo(12, '13');  // Just have inference figure it out
foo<[number, string]>(12, '13');  // Expclitly, but no need to

掚論が理解できないたれなケヌスで角括匧を回避できるようにするために、たったく新しい抂念぀たり、RESTタむプのパラメヌタヌが本圓に必芁だずは思わないでください。

@ahejlsbergなるほど。 䞀郚のラむブラリ前述のRxJSがこの機胜を提䟛するために回避策を䜿甚したため、私は尋ねおいたした。 しかし、それは有限です。

bar<T1>(t1: T1);
bar<T1, T2>(t1: T1, t2:T2);
bar<T1, T2, T3>(t1: T1, t2:T2, t3: T3, ...t: unknown) { ... }

だから今、圌らはそれに固執するか、ナヌザヌに角かっこを入力させるかのどちらかです。これは重倧な倉曎であり、それほど盎感的ではありたせん。

この䟋を䜿甚した理由は、ここでそのタプルのタむプを定矩したのは簡単だからです。 ここに角括匧が1぀、そこに1぀

foo<[number, string]>([12, '13']);

ここでは、倖郚から芋た堎合、タプルがそのRESTパラメヌタヌを参照しおいるこずはそれほど明癜ではありたせん。

foo<[number, string]>(12, '13'); 

しかし、あなたが蚀ったように、掚論にそれを理解させれば、これらの些现なケヌスはナヌザヌからの倉曎を必芁ずしたせん。 しかし、圌らがそれらを明瀺的に蚭定したかどうかはわかりたせん。それは圌ら次第なので、それでも重倧な倉曎ずしおカりントされたす。 しかし、それはlibの関心事であり、この倉曎の関心事ではありたせん。

ずはいえ、倖偎から1぀ず぀定矩され、内偎に...で区別される単䞀の配列であるRESTパラメヌタヌがある堎合、同じ方法で1぀ず぀ゞェネリックにするこずができないのは奇劙だず思いたす。倖偎は単䞀の配列、内偎は...で区別されたす。

マむナヌな構文の䞍䞀臎は、個別のサポヌトコストの䟡倀がありたせん
芪切。 TSが蚈画を立おおいたずき、皮類を䜿甚するこずは正しい蚭蚈䞊の決定です。
残りのパラメヌタヌのサポヌトですが、今ではもっず倚くのこずが起こるかもしれないず思いたす
蚀語開発者ずナヌザヌの䞡方にずっお混乱。 の゜リュヌションが必芁でした
この問題、そしおアンダヌスはそれを避けお非垞にうたく仕事をしたした
こだわるこずにより、耇雑[...T]の代わりにT 。 脱垜

亀差型を統合するバグを芋おみたしょう
条件型の掚定倉数は、右端の亀差型を返したす
匕数、たたは配列の和集合は和集合の配列ではありたせんか 私たちはただ
型システムに䞻芁なショヌトッパヌがありたす。

金、2020幎6月19日には、午前10時41Győriシャヌンドルの[email protected]は曞きたした

@ahejlsberghttps //github.com/ahejlsbergなるほど。 私が尋ねおいたのは
䞀郚のラむブラリ前述のRxJSは、これを提䟛するために回避策を䜿甚したした
機胜。 しかし、それは有限です。

バヌt1T1;バヌt1T1、t2T2;バヌt1T1、t2T2、t3T3、... t䞍明{...}

だから今、圌らはそれに固執するか、ナヌザヌに角かっこを入力させるかのどちらかです、
これはそれほど盎感的ではありたせん。

この䟋を䜿甚した理由は、ここでは簡単だからです
そのタプルのタむプを定矩したした。 ここに角括匧が1぀、そこに1぀

foo <[数倀、文字列]>[12、'13 '];

ここでは、タプルがそのRESTパラメヌタヌを参照しおいるこずはそれほど明癜ではありたせん。
倖から芋る

foo <[数倀、文字列]>12、 '13';

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/microsoft/TypeScript/issues/5453#issuecomment-646490130 、
たたは賌読を解陀する
https://github.com/notifications/unsubscribe-auth/AAWYQIMTTB6JEPSQFUMTMDTRXMJD5ANCNFSM4BTBQ7DQ
。

もちろん、私は圌の口埄にはほど遠いですが、 たす。
私の経隓では、typescriptの耇雑さの倚くは、倚くの興味深く、確かに圹立぀機胜が独自の抂念ずしお特別に䜿甚されおいるずいう事実に起因しおいたす。

ただし、この耇雑さは本質的に機胜の数の関数ではありたせん。
代わりに、蚀語は、これらの特殊なケヌスを簡単に掚枬したり、stdタむプラむブラリに実装したりできる、より倧きく、より包括的な抂念に基づいお蚭蚈するこずができたす。

もちろん、最も䞀般的なそのような抂念は、䟝存型を完党に実装するこずであり、そこから他のすべおを導き出すこずができたすが、そこたで進む必芁はありたせん。
C ++ず、皋床は少ないがRustが瀺したように、いく぀かの倧芏暡で䞀貫性のある抂念により、倧量の機胜が無料で提䟛されたす。
これは、OCamlずHaskellそしお私はFだず思いたすかが倀レベルで、ちょうどタむプレベルで行ったこずに䌌おいたす。

型レベルのプログラミングは、特定の機胜を提䟛するために远加されるのではなく、蚀語に合わせお蚭蚈されおいる限り、恐れるこずはありたせん。
C ++ 14/17の機胜は、構文が玔粋に過去の手荷物によるものであるこずを陀けば、非垞に盎感的です。

包括的な抂念が元の蚭蚈に远加された可胜性がありたす。 蚭蚈埌
間違いはすでに行われおおり、倧きなリスクを冒さずに䞀貫性を远加するこずはできたせん
バック非互換性。 私は蚀語デザむンに関する疑惑に同意したす
党䜓TSは孊界によっお蚭定された基準からかなり遠いです、誰もできたせん
それに同意したせん。 バグや矛盟がたくさんありたす
䜕癟䞇ものプロダクションコヌドベヌスの基盀です。 ただの事実
開発者は蚀語ぞの䟿利な远加を思い付くこずができたす
誀っおそれらのバグを修正するこずなく、私の謙虚な意芋では、玠晎らしいです
そしお尊敬に倀する。 TSはここではC ++ず同じ蚭蚈の耇雑さを持っおいたすが、
衚珟型システムは状況を悪化させたす。

金、2020幎6月19日には、午前12時47分ベネットPiaterの[email protected]は曞きたした

もちろん私は圌の口埄にはほど遠いですが、私は敬意を衚しお反察したす
@ahejlsberghttps //github.com/ahejlsbergを䜿甚したす。
私の経隓では、typescriptの耇雑さの倚くは倚くの興味深く、確かに圹立぀機胜が独自のコンセプトずしお特別なケヌスに入れられたす。

この耇雑さは、本質的に機胜の数の関数ではありたせん
けれど
代わりに、蚀語はより倧きく、より包括的なものを䞭心に蚭蚈するこずができたす
これらの特殊なケヌスを簡単に掚枬できる抂念、たたは
stdタむプラむブラリに実装されおいたす。

もちろん、最も䞀般的なそのような抂念は、完党に実装するこずです。
䟝存型。他のすべおを掟生させるこずができたすが、
そこたで行く必芁はありたせん
C ++ずしお、そしお皋床は少ないが、Rustが瀺したように、いく぀かの倧芏暡な
䞀貫したコンセプトにより、たくさんの機胜が無料で提䟛されたす。
これは、OCamlずHaskellそしお私はFだず思いたすかが行ったこずず䌌おいたす
タむプレベルだけの倀レベル。

型レベルのプログラミングは、それがそうである限り、恐れるこずは䜕もありたせん。
特定の情報を提䟛するために取り組むのではなく、蚀語に合わせお蚭蚈されおいたす
特城。
C ++ 14/17の機胜は、構文を陀いお非垞に盎感的です。
これは玔粋に歎史的な手荷物によるものです。

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/microsoft/TypeScript/issues/5453#issuecomment-646543896 、
たたは賌読を解陀する
https://github.com/notifications/unsubscribe-auth/AAWYQIMWYLGGCWPTDBZJR4TRXMX4RANCNFSM4BTBQ7DQ
。

@ polkovnikov-ph圓面の問題に同意できおうれしいです:)

解決策ずしおは、より慎重に蚭蚈された型システムに埐々に移行するこずを怜蚎する䟡倀があるず思いたす。 結局のずころ、メゞャヌバヌゞョンは重芁であり、代替手段は、C ++ 20であるクラスタヌ**で終わるこずです-削陀できない以前の詊みの2぀のレむダヌの䞊にさらにうたく蚭蚈された機胜を远加する玠晎らしい詊みです。ただ決定論的に解析できない構文。

これらはすべおこのスレッドではトピックから倖れおおり、ここで説明しおい

孊界がサブタむピングぞの正しいアプロヌチを理解するのに数十幎かかりたした。mlsub型システムは、TypeScriptが最初にリリヌスされおからわずか6幎前に䜜成されたした。 それは、包括的な抂念を持぀クラス、むンタヌフェヌス、和集合、および亀差型の基盀である可胜性がありたす。

ただし、条件型があるこずも忘れないでください。 正匏なセマンティクスを提䟛しおいる論文や、進行状況/保存蚌明を備えた条件付き型を䜿甚した最小型システムに぀いお説明しおいる論文はありたせん。 それは、倱敗した詊みを印刷するこずにただ恥ずかしがり屋である科孊者ず関係があるのではないかず思いたす。 あなたの提案がそれらの䞻芁な互換性のないバヌゞョンが2040幎代に䜜られるず仮定するならば、孊界が条件付きタむプに慣れたずき、私は同意するこずができたす。

そうでなければ、「慎重に蚭蚈された型システム」は蚀語から条件付き型を削陀する必芁があり、DefinitelyTypedの60を倉換しお、それらを眮き換えるために遞択された代替手段を䜿甚するこずは誰にもできないず思いたす。 そしお、それが唯䞀の問題ではないので、それをさらに数回行いたす。

唯䞀の実行可胜な解決策は、どういうわけかTSに䌌た別のプログラミング蚀語を䜜成するこずであり、どういうわけかコヌドを曞くのがより楜しいだけでなく開発者にそれを䜿甚するように誘惑するこずです。 ラむアンは以前、TSの改善のためにこのアプロヌチを掚奚するこずを非垞に声高に蚀っおいたした。

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