-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue deriving tuple types on overridden method #57387
Comments
Methods don't inherit the types of the methods they're overriding, so the type of your |
I suppose that's fair, though from an ergonomics perspective it feels odd to me that TS would mark a type mismatch between In a TypeScript-forward project, where relying on implicit types is generally discouraged, the current behavior may be completely reasonable; I'm running into this in a Javascript project with JSDoc types, and the lack of inference is an unfortunate hurdle for most consumers (especially as the tuple type gets pushed deeper inside a nested object). |
You can't really remove this inconsistency, only change where it appears. If you had written this, for example, class Bar extends Foo {
spec() {
const m = ["goodbye", {something: "else"}]
return m;
}
} |
@RyanCavanaugh I'm not sure I follow your argument. In your example, On the other hand, To someone unfamiliar with the implementation of TypeScript, it definitely feels like a defect to say that a hard-coded value like |
Arrays can be empty, not having a |
Fair point. |
@pvande the vibes might be off, but the "fix" is that the method return type inference algorithm gets more complex (and very much more non-local in this case), and "the type system is too complicated to understand" is already a problem that people talk about. Everything can be made more complicated, but complexity itself is also understood to be a defect. It's not infrequent for people to claim that the inference system should be "worse" (less likely to understand implicit intent) for the sake of being "simpler". I'm not saying this is an absolute must-not-change, but it's also not a bug in the sense of producing unsound behavior. And even in the presence of a fix, |
@RyanCavanaugh Thanks for your patience with me about this.
That does seem likely.
Not being a regular member in this community, that's not something I've been aware of, though it also seems reasonable.
Completely agree. At worst, it's a spurious error in VS Code for folks leveraging a typed API in a typeless Javascript project.
I can imagine a world in which implicitly typed literals are lazily evaluated and "cast" at point-of-use. In such a world, all of the following seem reasonable: const value = ["string", {number: 2}, /s/]
let a: [string, ...any] = value
let b: [any, {number: number}, any] = value
let c: [...any, RegExp] = value
let d: Array<string | {number: number} | RegExp> = value
function e(arg: [string, ...any]): void { arg }
e(value)
const f = () => value
a = f()
b = f()
c = f()
d = f() What I don't know offhand is what the practicalities and drawbacks of such an implementation are, though I'm confident they exist. That said, my only goal in opening this issue was to call attention to a sharp edge that my team encountered, to raise awareness and discussion. |
This is an interesting thought and not something I personally ever considered. One of the fundamental tradeoffs you make with a typed language is that you give up the ability to speak of individual values in favor of giving the compiler (and potentially, the programmer) an easier job by being able to reason about more general types (i.e. constraints) of values instead. But I could definitely imagine a world too where e.g. object and array literals (which might satisfy several different constraints thanks to contextual typing) have type inference "deferred" until they're actually assigned to something with an explicit type annotation. That said, deferral brings with it its own problems. See, e.g. conditional types in a generic context. |
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
π Search Terms
tuple type infer inference inheritance
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play?alwaysStrict=false&target=2&jsx=0&module=5&ts=5.3.3&filetype=ts#code/CYUwxgNghgTiAEAXAngBwQZUTAlgOwHMAxHGAZ0QBUBXVCBAXngG0LdCAaeAOl6j2QBdANwAoUZChky8IgHs58AN6j4a+GXRgAFAEoAXPCztipCjToIV6m-DiJqMPCwBEACxAQIcl4NXqAX1EgiWhpeAAhWHgQAA9EEDxgGXlFa3VNcD1lf1s7EAcnVwIFYAAjZBAXLiUyOQBbArd8AkMXTzIqgL8bIICgA
π» Code
π Actual behavior
The
spec
method onBar
failed to typecheck, despite unambiguously implementing the same type signature asspec
onFoo
.Annotating
Bar
'sspec
method to return aStringFirstTuple
typechecks properly.The error message seems to indicate that the return type of
spec
inBar
has been generalized toArray<string | {something: string}>
before checking the overridden type.π Expected behavior
A function that returns an array that is hard-coded to match a tuple type should be substitutable for a function that is specified to return that tuple type.
Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: