-
Notifications
You must be signed in to change notification settings - Fork 327
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
Surprising acceptance of various inputs #690
Comments
For 1, TypeScript tuple are arrays, in multiple senses. First, tuples are arrays in a literal sense in that JavaScript doesn't have "tuples". So, at runtime, anything that was a "tuple" in your TypeScript code really is a JavaScript Array at runtime. Second, even in TypeScript's type system, tuples are a subtype of Arrays. So, any function that accepts an array of a certain element type will also accept tuples of any arity as long as the elements in the tuple are compatible with the element type of the array in the signature. For 2, this is also consistent with how JavaScript and TypeScript work (try passing a Record<number, string> to a function that accepts Record<string, string> and vice versa). Though, I suppose the documentation should be changed to not be misleading. Same with 3. It's unfortunate, but JavaScript object keys are never really numbers. They always get converted to numbers. For example, this is valid: 4 is somewhat debatable, but I don't think it should work the way you're describing. TypeScript is primarily structurally typed, which means that types/interfaces describe a minimum requirement of a type. So, a TypeScript type will accept an object with "extra" fields as correct. The current io-ts behavior is consistent with that philosophy, and all strict/exact do is to actually strip those extra fields for us. It would be strange and inconsistent with the rest of TypeScript to reject objects with extra fields. 5 is the only one that I agree is troublesome. There are other issues that discuss io-ts's take on |
🐛 Bug report
Current Behavior
For educational purposes, I played around with the available codecs and encountered these (in my opinion erroneous) cases:
t.UnknownArray
accepts["ABC", 123]
which is a tuple, not an array.t.UnknownRecord
acceptsconst n: number = 7; const x: Record<number, string> = {[n]: "n"};
although the documentation claims that it accepts onlyRecord<string, unknown>
i.e. string keys.t.record(t.string, t.number)
acceptsconst n: number = 7; const x: Record<number, number> = {[n]: 888};
although the key is a number, not a string.t.strict({ a: t.number, b: t.string })
accepts{a: 777, b: "Hello", also: "x", and: 123}
although it should reject objects with extra fields. The same holds true whent.strict
is replaced byt.exact(t.type(...))
.t.partial({a: t.string})
accepts{a: undefined}
even when"exactOptionalPropertyTypes": true
is set in tsconfig.jsonExpected behavior
Ideally all of the above codecs should reject the presented example objects.
For 2) and 3) I am not sure whether these are really distinguishable types in TypeScript? (If I change the Record type to
Record<string, ...>
I don't get a typing error.) If they are not distinguishable, the documentation should reflect this.Reproducible example
See above.
Suggested solution(s)
See above.
Your environment
Which versions of io-ts are affected by this issue? Did this work in previous versions of io-ts?
The text was updated successfully, but these errors were encountered: