-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add --strictObjectIterables
(bikeshed): exclude primitive (string
) from Iterable
types
#59676
Comments
"Old" functions such as |
The results at #59683 outline the difficulty of this. Looking at the code, we see a lot of places where people write code that takes an implicit dependency on the iterability of // https://github.com/refined-github/refined-github/blob/6e167b9d881bd05db8cb92a5e140144cda7fd873/source/features/quick-review.tsx#L18C1-L18C54
const emojis = [...'ππΏοΈβ‘οΈπ€π₯³π₯°π€©π₯Έππ€―π’π«π³οΈπ']; There's just a ton of code out there that takes inputs like URLs, hashes, file paths, programmer-authored strings, etc, and iterates it in a way that can't cause problems. We also see places where people forget that strings are iterable and end up passing e.g. // https://github.com/mui/material-ui/blob/8ab2137281267ad4fa766e4bd64d03baa5d44820/docs/data/material/getting-started/templates/dashboard/theme/themePrimitives.ts#L227
shadows: [
'none',
...(mode === 'dark'
? 'hsla(220, 30%, 5%, 0.7) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.8) 0px 8px 16px -5px'
: 'hsla(220, 30%, 5%, 0.07) 0px 4px 16px 0px, hsla(220, 25%, 10%, 0.07) 0px 8px 16px -5px'),
] as Shadows But both of these are just the same thing: spreading a string. The same thing happened for implicit Worse, the iterator capability of console.log("πͺ".length); // 2, probably expected 1
console.log([..."πͺ"].length); // single codepoint, ok-ish and we did see code that intentionally uses this behavior. We'd need some way to tell apart intentional from non-intentional iteration to proceed here, and one doesn't seem to exist in the type system. Open to ideas, though. |
Similar to what @nmain mentioned above perhaps |
Maybe add builtin type: // Like `Iterable<T, TReturn, TNext>`, but excludes strings
type StrictIterable<T, TReturn = any, TNext = any> = intrinsic; |
π Search Terms
"iterable object", "string"
β Viability Checklist
β Suggestion
At the TC39 meeting in 2024-07, it was decided that
Iterable
expects objects.https://github.com/tc39/how-we-work/blob/main/normative-conventions.md#reject-primitives-in-iterable-taking-positions
To follow this decision, the
Iterable
andstring
types should be separated, and APIs that accept both types should be required to explicitly specifyIterable<any> | string
. Since this would be a breaking change, how about adding a new--strictObjectIterables
(bikeshed) option?In practice, the upcoming
ReadableStream.from
will acceptIterable<any>
andAsyncIterable<any>
, but will be restricted to objects. whatwg/streams#1310π Motivating Example
Enabling the
--strictObjectIterables
option raises a type error in the following example:π» Use Cases
What do you want to use this for?
Used for
ReadableStream.from
and other APIs to be added in the future.What shortcomings exist with current approaches?
Iterable
object andstring
are not distinguished by default.What workarounds are you using in the meantime?
Maybe
Iterable<any> & object
can rejectstring
.The text was updated successfully, but these errors were encountered: