microsoft / microsoft/TypeScript
Mechanism for late inferred types in control flow analysis
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Go
- Star
- 111k
- Fork
- 14.4k
- Merge trung bình
- 1 ngày 19 giờ
- Pull request đã merge (30 ngày)
- 117
Mô tả
🔍 Search Terms
"control flow analysis" with variations of array, widening, callbacks, etc
✅ Viability Checklist
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ Suggestion
I have an issue where I want to capture a type defined in a scope that is inaccessible from my current scope. For example, I want to create a wrapper for some OpenAI function.
import 'openai'; // Just to get the types to load
type Magic = never;
// let expandingArray: Array<Magic> = []
let expandingArray = []
type Client = InstanceType<typeof import('openai').OpenAI>
const openai = {} as Client;
type Options = {
onMessageResponse: (message: typeof expandingArray[number]) => void
}
const doStuff = (options: Options) => {
openai.chat.completions.create({
model: 'chatgpt-4o-latest',
messages: []
}).then(response => {
const {role, ...rest} = response.choices[0].message
// Here's where I finally resolve how I want the shape to look like
expandingArray.push(
{...rest, type: 'my-custom-type' as const}
)
type Good = typeof expandingArray[number]; // Good is typed correctly but local to this scope
options.onMessageResponse(expandingArray[0]) // This should be type-safe and not just never
})
}
type Bad = typeof expandingArray;
As you can see, the goal is to have an auto-widening type based on usage later on (within the same file). This somewhat already works with control flow analysis for arrays, as you can see in the type Good = ... type above.
Realistically, when this situation occurs, application authors will type onMessageResponse as (message: any) => void, which is unfortunate because all the type information is there and just needs a way to be bubbled up to the higher scope.
It would be nice if there was an escape hatch to tell the type system that I care about the typeof a value declared somewhere inaccessible to the current type scope within the file. Obviously, this wouldn't actually use an untyped array with some annotation on the type; this would probably be a special new named type like LateInferredType or something similar, e.g.:
type Message = LateInferredType;
type Options = {
onMessageResponse: (message: Message) => void
}
/// ...
.then(response => {
const {role, ...rest} = response.choices[0].message
// Here's where I finally resolve how I want the shape to look like
const message = {...rest, type: 'my-custom-type' as const}
options.onMessageResponse(message as Message) // Perhaps casting signals to the type system to recognize it
})
Or perhaps there's a non-breaking way of declaring this syntax that I'm not thinking of.
📃 Motivating Example
This allows smarter inference without needing to chase down every derived property. Sometime the specific types aren't even exported by the upstream libraries and there's no good way to mention them without recreating a large complex type which is fragile and error prone.
💻 Use Cases
- What do you want to use this for?
This is useful for writing type safe code where you want to expose a complex type that doesn't have a concrete definition and is more tied to the specific shape of a single step in a complex application - What shortcomings exist with current approaches?
There's no way to signal later in a program or without a callback that a type should be widened, but sometimes that exact functionality is needed - What workarounds are you using in the meantime?
None
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu bằng cách tái hiện ví dụ Playground được liên kết và đọc phần thảo luận của issue về suy luận mảng trong control-flow. Một thay đổi hoàn chỉnh sẽ cần một cơ chế được quyết định để đưa kiểu được suy luận sau đó đến scope bên ngoài, với hành vi được xác định cho callback được hiển thị và các trường hợp kiểu không thể truy cập.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- typescript
- Lĩnh vực
- compilers
- Loại issue
- Tính năng
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Đình trệ
- Độ rõ ràng
- Cần làm rõ
- Mức phù hợp với người mới
- 25/100