microsoft / microsoft/TypeScript
Proposal: repurpose "is" operator for a narrowing version of "satisfies"
还没有人认领这个 Issue。
- 主要语言
- Go
- 星标
- 111k
- 派生
- 14.3k
- 平均合并
- 2 天 4 小时
- 30 天内合并 PR
- 132
描述
### 🔍 Search Terms
satisfies with narrowing
narrowing literals
satisfias, satisfiesas, sassafras
### ✅ Viability Checklist
- [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
- [x] This wouldn't change the runtime behavior of existing JavaScript code
- [x] This could be implemented without emitting different JS based on the types of the expressions
- [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- [x] This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- [x] This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
### ⭐ Suggestion
A narrowing version of the `satisfies` operator
```typescript
type Animal = "cat" | "dog";
const animal = "cat" is Animal;
/// ^? = Animal
```
### 📃 Motivating Example
Consider an API where the return type is influenced by the input type. For example, this simplification of [Tanstack Form](https://tanstack.com/form/latest/docs/overview) (I'm not a contributor to it, but I'm developing something similar).
```typescript
function useForm(defaultValues: T): T {
return /*something*/;
}
const values = useForm({
animal: "cat"
});
```
The type inferred from animal here is `string`.
This works fine if animal is a text input in our form, but what if we want it to be an enumeration, e.g. ``, and also retain some compile-time typechecking? e.g. we want to prevent this
```typescript
values.animal = "red"
```
`satifies` will error if the initial value is not valid, but it doesn't narrow the type:
```typescript
// #1
const values = useForm({
animal: "cat" satisfies Animal
});
// typeof values["animal"] = string
```
`as` achieves the equivalent of narrowing here, but it masks some errors:
```typescript
// #2
const values = useForm({
animal: "red" as Animal // no error
});
```
I propose to repurpose the existing `is` keyword. Could use another keyword; bikeshed it later.
```typescript
const values = useForm({
animal: "cat" is Animal
});
```
This would produce a compiler error if the left hand side was not an Animal (like satifies), but additionally narrow the type to Animal.
### 💻 Use Cases
**What shortcomings exist with current approaches?**
A more natural flow of the code is disrupted; the field can't be declared inline.
**What workarounds are you using in the meantime?**
This one is okay, but somewhat disrupts the flow of reading top to bottom.
```typescript
// #3
const initialAnimal: Animal = "cat";
const values = useForm({
animal: initialAnimal,
plainString: "a",
plainNumber: 1
});
```
This one requires declaring the entire type separately. Also there may be many more type args than just the data shape. This is the case in Tanstack Form. You'd need `useForm`;
```typescript
// #4
type FormValues = {
animal: Animal
}
const values = useForm({
animal: "cat"
});
```
This is probably what I find myself reaching for, but as with `#4` requires declaring the entire type
```typescript
// #5
type FormValues = {
animal: Animal
plainString: string
plainNumber: number
}
const initialValues: FormValues = {
animal: "cat",
plainString: "",
plainNumber: 0
}
const values = useForm(initialValues);
```
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
未指定实现文件、测试或入口点。首先查看现有的 `satisfies` 运算符以及示例中描述的类型断言行为,然后确定 `is` 的一种缩窄形式如何适配编译器的类型系统设计。当提案具有已接受的设计,并且实现和测试范围已定义时,即视为完成。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- typescript
- 领域
- compilers
- Issue 类型
- 功能
- 难度
- 5/5
- 预计耗时
- 一周以上
- 活跃度
- 停滞
- 描述清晰度
- 基本清楚
- 新手友好度
- 30/100