Skip to content
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

TS 4.7 Beta: Object access should be narrowable after check #48802

Closed
kyliau opened this issue Apr 21, 2022 · 6 comments
Closed

TS 4.7 Beta: Object access should be narrowable after check #48802

kyliau opened this issue Apr 21, 2022 · 6 comments

Comments

@kyliau
Copy link
Contributor

kyliau commented Apr 21, 2022

If I read the release blog post for v4.7 Beta correctly, the following test case should work, but it still produces an error.

interface Foo {
  [key: string]: number | string;
}

declare function generateKey(): string;

function fn(foo: Foo) {
  const key = generateKey();
  if (typeof foo[key] === 'number') {
    foo[key].toExponential(2);
    // Error: Property 'toExponential' does not exist on type 'string | number'.
  }
}

Is this a bug?

TS Playground Link v4.7.0-dev.20220420

If this only works for object access with Symbol, it should be clarified in the blog post.

FWIW, here's the example from the blog post (which works):

const key = Symbol();

const numberOrString = Math.random() < 0.5 ? 42 : "hello";

let obj = {
    [key]: numberOrString,
};

if (typeof obj[key] === "string") {
    let str = obj[key].toUpperCase();
}

Originally posted by @kyliau in #45974 (comment)

@kyliau kyliau changed the title Object access should be narrowable after check TS 4.7 Beta: Object access should be narrowable after check Apr 21, 2022
@jcalz
Copy link
Contributor

jcalz commented Apr 21, 2022

Isn’t that feature about computed properties, specifically? I don’t see a computed property in your example.

@IllusionMH
Copy link
Contributor

In your initial example there are no computed properties - Foo has just index signature. Only similar - both use indexed access to get value, but while it's know symbol in blog post, you just check for random string.

@kyliau
Copy link
Contributor Author

kyliau commented Apr 21, 2022

Thanks for the clarification! It took me a while to find the proper documentation for "computed properties".
For anyone else who has the same question, I find this article most helpful: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-9.html

Closing issue.

@kyliau kyliau closed this as completed Apr 21, 2022
@andrewbranch
Copy link
Member

I just reread @a-tarasyuk’s PR and the logic isn’t specific to computed properties (that was just the motivation for narrowing element accesses). The reason this isn’t narrowing is that the type of the argument expression (key in foo[key] in your example) has to be a unique symbol or string or number literal. In your example, it’s string. If you could know that its type was, say, "this_string_in_particular", you would be allowed to narrow with that. Here’s a modified playground showing the difference—obviously that’s not going to be adaptable to your use case, but hopefully it helps clear up the requirements.

I agree the release notes were not clear about this, though maybe the constraints mean that this is really only particularly useful for computed properties.

@andrewbranch
Copy link
Member

I also noticed that the predicate on the name type uses its declared type, not its flow type. I’m not sure if there was a reason we couldn’t use the flow type or if there just wasn’t a strong reason to do it. I can’t really come up with an example that looks natural.

@lobotomoe
Copy link

I’m not sure if there was a reason we couldn’t use the flow type or if there just wasn’t a strong reason to do it. I can’t really come up with an example that looks natural.

Hey, @andrewbranch , are you still can't come up with an example? I try to find some explanation for that behaviour. Possibly you can point me some docs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants