-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Unable to use rest on generic that has been narrowed to an object #59872
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
Comments
The error is correct; these narrowings are not equivalent. Knowing that const fn1 = <T extends string | { toFixed(): string }>(v: T) => {
if (typeof v === 'string') {
return { text: v };
}
const { ...rest } = v;
return { text: '???', ...rest };
};
fn1(42); |
Right, so effectively this is me forgetting that this is "types on a dynamic runtime" rather than Go or Rust or whatever where it could only be those two types - my general thinking was it sufficient as I'd told TS its either "x or y" and then checked if it was "y" so the opposite branch should then be "x"... I'm trying to think why that trips me up though - I feel like TS does behave like this elsewhere, but maybe I'm just misremembering some subtilties 🤔 (also I realised I've left out my truthy check which'd mean the whole "null is an object" thing in theory shouldn't be relevant - I'm pretty sure that doesn't matter for my simple example, but would for more real-world code) |
actually maybe this is more about TS not having a difference between "pure data type object thing" and ... idk what to call the alternative - things with methods.? it's not that though but just i.e. in my head I'm thinking "this function takes a plain object with some properties", but you've shown TS actually checks for something slightly different meaning depending on your type something like a primitive could be considered valid for what looks like an object type, and then boom here we are... |
If you can write |
That makes sense - it's that an "object" is different from "a value with properties", and that really TS's syntax describes the latter rather than the former (which makes sense because that's the underlying principle of duck typing, which is what JS is doing). Happy for this to be closed, and thanks for working this through with me 🙂 |
🔎 Search Terms
"Rest types may only be created from object types" (and similar keyword-based rephrasing/shortenings)
🕗 Version & Regression Information
⏯ Playground Link
https://www.typescriptlang.org/play/?#code/PTAEDMCcHsFtQBYBckAcDOAuEBzAlkggK4BGAdAMZzCx4UzrThLAAqAnqgKYDK9eqFnnToiXdMABMANgAsARkkBYAFDgiAOwpI80DaHQIAhgBsT0AO4BhaKnYAeVqC4APJFw0ATdKGgkAVlzaAHwAFOhIRu6YoKwAlDFOAN6qoKCQXEhEkPpJoGQFEVFcoAC+ANyqpaqqVBoREBryoAC8oI7Obh7eBkiQeBo4oAA+oHmoRpDoXJAxEf2DZWEAbolxrcFjqaB44KChSJxcTKDLrS1tAOTzAziX6ykqaWkZWTljoO5uMWcV29UqbZ1Bp5ApkDINUqtU6VQFPdKZbK5T6uJAxS4AfixlwANPkChCkGVYX84cCieANJJoR1Ud0fDdFqNxpNprNegshqUVmsNlt4bt9oduCczgBCC6gS5+QLae7854It7Ir5o07E-41eHkj5gwllaHLWHbV5Ij6q9FYjG4-Hg8RE0kVIA
💻 Code
🙁 Actual behavior
The middle function has the error "Rest types may only be created from object types"
🙂 Expected behavior
No errors in any of the functions
Additional information about the issue
This looks like #26412 with just an extra twist - I figure (and hope) it's fixable since it works with the inverse
!== 'object'
check.For a more real-world code example, I came across this when exploring a potential refactor to this section of code where I'd use spread/rest rather than a loop (so the proposed next line after that condition is
const { a, b, c, ...remainingOptions } = config;
, which triggers this)The text was updated successfully, but these errors were encountered: