Infer from usage type logic
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Cần làm rõ
- Mức độ hoạt động
- Đình trệ
- Công nghệ
- typescript
- Lĩnh vực
- compilers
Hướng nghiên cứu
Bắt đầu với TypeScript/src/services/codefixes/inferFromUsage.ts và so sánh các trường hợp Playground được liên kết với combineAnonymousTypes và combineTypes. Theo dõi logic thuộc tính tùy chọn và bảng mức độ ưu tiên, sau đó xác định hành vi suy luận dự kiến trước khi thay đổi bất kỳ điều gì. Hoàn tất khi các trường hợp suy luận từ cách sử dụng được báo cáo không còn tạo ra lỗi kiểu dữ liệu ngoài dự kiến.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Bug Report
🔎 Search Terms
- infer from usage
- interface higher priority then type on type inference
🕗 Version & Regression Information
I think this has always been the behavior as far as I know. I didn't play around with this much yet, but the behavior exists in 4.0.5 and nightly and it seems odd for it to bounce around a lot.
⏯ Playground Link
💻 Code
// infers -> : { x: any; } = this makes sense
function inferWorksFine(obj) {
return obj.x
}
// infers -> Z, this also makes sense
function inferFromFunctionCallTypedWithType(obj) {
typedWithType(obj)
}
// infers -> Q, also makes sense
function inferFromFunctionCallTypedWithInterface(obj) {
typedWithInterface(obj)
}
/*
* Here is when behavior gets odd
*
*/
// infers -> { toplevel?: any; z?: number }
// I would prefer if toplevel resovled to a non ? type but thats sorta stylistic
// z is not optional and making it results in a type error
function inferFromUsageAndFunctionCallTypedWithType(obj) {
typedWithType(obj)
return obj.toplevel
}
// infers -> Q
// This seems wrong to me, interface "types" have priority over
// anonymous types, this results in errors because the inferred property
// is an anonymous type
function inferFromUsageAndFunctionCallTypeWithInterface(obj) {
typedWithInterface(obj)
return obj.toplevel
}
// infers -> Q
// From what I understand. The statement "type Z = {z: number}"
// is a type alias Z to an anonymous type {z: number} so the interface
// still has priority over it.
function inferFromFunctionCallTypedWithTypeAndFunctionCallTypedWithInterface(obj) {
typedWithType(obj)
typedWithInterface(obj)
}
// There are more examples you could contrive that look like this/combinations of this
// but I think this is enough for the point
type Z = {z: number}
function typedWithType(z: Z) {
}
interface Q {
q: number
}
function typedWithInterface(q: Q) {}
🙁 Explanation of Actual behavior
Note: If I reference line numbers or any function I'm referring to the main branch I pulled I think yesterday.
So I sort of already discussed the behavior in the code itself. So I think it makes sense to talk about the code that causes this behavior.
So this file path "TypeScript/src/services/codefixes/inferFromUsage.ts" is where the logic for inferFromUsage lives afaik.
Just to do this in order:
// infers -> { toplevel?: any; z?: number }
// I would prefer if toplevel resovled to a non ? type but thats sorta stylistic
// z is not optional and making it results in a type error
function inferFromUsageAndFunctionCallTypedWithType(obj) {
typedWithType(obj)
return obj.toplevel
}
The reason these are optional seem to stem from the function combineAnonymousTypes
Specifically
const members = mapEntries(props, (name, types) => {
const isOptional = types.length < anons.length ? SymbolFlags.Optional : 0;
const s = checker.createSymbol(SymbolFlags.Property | isOptional, name as __String);
s.links.type = checker.getUnionType(types);
return [name, s];
});
I'm actually not sure what the isOptional is intended to do. From what I understand anons.length is the number of anonymous types that the function is passed while types refers to possible type resolutions of the property with name name. I'm not sure what comparing these means.
Priority of interfaces
Since in the code I mention why I think type aliasing doesn't change anything I'll just show one example.
function inferFromFunctionCallTypedWithTypeAndFunctionCallTypedWithInterface(obj) {
typedWithType(obj)
typedWithInterface(obj)
}
So here the type will be resolved to the interface type. In the function combineTypes there is a priority table defined as follows:
const priorities: Priority[] = [
{
high: t => t === checker.getStringType() || t === checker.getNumberType(),
low: t => t === stringNumber
},
{
high: t => !(t.flags & (TypeFlags.Any | TypeFlags.Void)),
low: t => !!(t.flags & (TypeFlags.Any | TypeFlags.Void))
},
{
high: t => !(t.flags & (TypeFlags.Nullable | TypeFlags.Any | TypeFlags.Void)) && !(getObjectFlags(t) & ObjectFlags.Anonymous),
low: t => !!(getObjectFlags(t) & ObjectFlags.Anonymous)
}];
The last entry
{
high: t => !(t.flags & (TypeFlags.Nullable | TypeFlags.Any | TypeFlags.Void)) && !(getObjectFlags(t) & ObjectFlags.Anonymous),
low: t => !!(getObjectFlags(t) & ObjectFlags.Anonymous)
}
gives high priority to non-anonymous types which I think only means interfaces or a type which at some point was mixed with an interface? This would take further investigation. I'm not sure the purpose of this behavior or if its a bug.
🙂 Expected behavior
I want the behavior to be that the generated types don't cause errors when they don't have to, since currently generated types don't satisfy what they need to be.
Deleting these two lines "solves" the behavior, but there are definitely more things to look into. I'm not sure why they were written - like I don't have any intuition on what problem they solve - but I'm pretty sure they are there for important behavior.
Also since I'm listing things, I think this is the other "big one"
There are also more cases like
function f(obj) {
g(obj)
return obj.v > 1
}
not being able to resolve v to a number if "g" expects some type (even if the type is unrelated like {q}) and others.
- 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
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.
Issue khác của microsoft/TypeScript
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
microsoft/TypeScript#64322 · 2 bình luận · 1 reaction · 2 người được giao ·
-
Possible Improvement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
microsoft/TypeScript#64278 · 1 bình luận · 1 reaction ·
-
Docs
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
microsoft/TypeScript#64118 · 1 bình luận ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
microsoft/TypeScript#64094 ·
-
Docs
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
microsoft/TypeScript#63959 · 5 bình luận ·
Tất cả issue của microsoft/TypeScript
Issue tương tự
-
optimization optimization:agents-md-curator
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 86/100
githubnext/gh-aw-cao#13143 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
blinklabs-io/bursa#904 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 84/100
yanet-platform/ipfw-go#129 ·
-
bug confmap/provider/googlesecretmanagerprovider needs triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
open-telemetry/opentelemetry-collector-contrib#51273 · 2 bình luận ·
-
bug: AI Gateway client filter lists "Unknown" twice when NULL and literal Unknown clients coexist Đang mởbug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 90/100