镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

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

Description

@kyliau

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 Keen (@kyliau) in #45974 (comment)

Activity

changed the title [-]Object access should be narrowable after check[/-] [+]TS 4.7 Beta: Object access should be narrowable after check[/+] on Apr 21, 2022

jcalz commented on Apr 21, 2022

@jcalz
Contributor

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

IllusionMH commented on Apr 21, 2022

@IllusionMH
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 commented on Apr 21, 2022

@kyliau
ContributorAuthor

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.

andrewbranch commented on Apr 25, 2022

@andrewbranch
Member

I just reread Oleksandr Tarasiuk (@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 commented on Apr 25, 2022

@andrewbranch
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 commented on Jun 9, 2022

@lobotomoe

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, Andrew Branch (@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?

locked as resolved and limited conversation to collaborators on Oct 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions