microsoft / microsoft/TypeScript

'identity' modifier to indicate a function's parameter-less returns should be narrowed like a value

オープン
#60,948 コメント 39 件 リアクション 136 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

Needs More Info
主要言語
Go
スター
111k
フォーク
14.4k
平均マージ
1日 19時間
マージ済み PR(30日)
117

説明

🔍 Search Terms

indicate function returns identical value cached memoized signals

✅ Viability Checklist
⭐ Suggestion

Many apps today are built on the concept of using small "getter" functions as wrappers around values. For example, Signals as implemented in Angular, Solid, and the stage 1 TC39 Signals proposal often look something like:

declare const value: () => string | undefined;

if (value() !== undefined) {
  console.log(value().toUpperCase());
}

Signals users have struggled with using them in TypeScript because, at present, there isn't a way to get that code block to type check without type errors. Signals users know that the result of value() must be string inside the if, but TypeScript doesn't have a way to note that the result should be type narrowed. Common workarounds today include !, ?., and refactoring to store intermediate values. All of which are at best unnecessary verbosity, and at worst conflict with frameworks.

Request: can we have a keyword -or, failing that, built-in / intrinsic type- to indicate that calls to a function produce a referentially equal, structurally unchanging value? In other words, that the function call (value()) should be treated by type narrowing as if it was just a variable reference (value)?

Proposal: how about an identity modifier keyword for function types that goes before the ()? It would be treated in syntax space similarly to other modifier keywords such as abstract and readonly.

📃 Motivating Example

When an identity function is called, it is given the same type narrowing as variables. Code like this would now type check without type errors, as if value was declared as const value: string | undefined:

declare const value: identity () => string | undefined;

if (value() !== undefined) {
  value();
  // Before: string | undefined
  // Now: string

  console.log(value().toUpperCase());
  // Before:  ~~~~~~~ Object is possibly 'undefined'.
  // Now: ✅
}

Narrowing would be cleared the same as variables when, say, a new closure/scope can't be guaranteed to preserve narrowing:

declare const value: identity () => string | undefined;

if (value() !== undefined) {
  setTimeout(() => {
    value();
    // Still: string | undefined

    console.log(value().toUpperCase());
    // Still:   ~~~~~~~ Object is possibly 'undefined'.
  });
}
💻 Use Cases

One difficult-to-answer design question is: how could identity handle functions with parameters? I propose the modifier not be allowed on function signaturess with parameters to start. It should produce a type error for now. The vast majority of Signals users wouldn't need signatures with parameters, so I don't think solidifying that needs to block this proposal. IMO that can always be worked on later.

Furthermore, it's common for frameworks to set up functions with a parameter-less "getter" signature and a single-parameter "setter" signature. I propose for an initial version of the feature, calling any other methods or setting to any properties on the type should clear type narrowing:

declare const value: {
  identity (): string | undefined;
  (newValue: string | undefined): void;
}

if (value() !== undefined) {
  value("...");

  value();
  // Still: string | undefined

  console.log(value().toUpperCase());
  // Still:   ~~~~~~~ Object is possibly 'undefined'.
}

More details on the difficulties of signals with TypeScript:

If a new modifier keyword isn't palatable, a fallback proposal could be a built-in type like Identity<T>. This wouldn't be a new utility type (FAQ: no new utility types); it'd be closer to the built-in template string manipulation types.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

Issue にある動機となる TypeScript の例から始め、リンクされている Angular と Solid の議論、および参照されている TypeScript のコメントを確認してください。リポジトリのファイルやテストは指定されていません。実装と検証に先立ち、identity function の型、narrowing の挙動、パラメーター、invalidiation について合意された設計が必要です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
typescript
領域
compilers
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。