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

Type guard not applied based on indexed access with string literal #26232

Description

@dalen

TypeScript Version: 3.1.0-dev.20180804

Search Terms:
dash, bracket

Code

Very similar to documentation example code, but with a discriminant containing a dash. Likely not because of the dash itself, but because the lookup is using s['kind-of'] instead of s.kind.

interface Square {
  'kind-of': 'square';
  size: number;
}

interface Rectangle {
  'kind-of': 'rectangle';
  width: number;
  height: number;
}
type Shape = Square | Rectangle;

function area(s: Shape): number {
  if (s['kind-of'] === 'square') {
    // Now TypeScript *knows* that `s` must be a square ;)
    // So you can use its members safely :)
    return s.size * s.size;
  } else {
    // Wasn't a square? So TypeScript will figure out that it must be a Rectangle ;)
    // So you can use its members safely :)
    return s.width * s.height;
  }
}

Expected behavior:

No errors

Actual behavior:

test.ts:17:14 - error TS2339: Property 'size' does not exist on type 'Shape'.
  Property 'size' does not exist on type 'Rectangle'.

17     return s.size * s.size;
                ~~~~

test.ts:17:23 - error TS2339: Property 'size' does not exist on type 'Shape'.
  Property 'size' does not exist on type 'Rectangle'.

17     return s.size * s.size;
                         ~~~~

test.ts:21:14 - error TS2339: Property 'width' does not exist on type 'Shape'.
  Property 'width' does not exist on type 'Square'.

21     return s.width * s.height;
                ~~~~~

test.ts:21:24 - error TS2339: Property 'height' does not exist on type 'Shape'.
  Property 'height' does not exist on type 'Square'.

21     return s.width * s.height;
                          ~~~~~~

My real world use case is to check type of AWS Cloudwatch event using the detail-type field on the event, so can't just change the name to get around the restriction easily.

Activity

  1. RyanCavanaugh commented on Aug 6, 2018

    @RyanCavanaugh
    Member

    It's the use of bracket notation (x["a"]) rather than dot (x.a) that causes this

  2. changed the title [-]Discriminated unions not working when discriminant contains dash[/-] [+]Type guard not applied based on indexed access with string literal[/+] on Aug 6, 2018
  3. ahejlsberg commented on Aug 6, 2018

    @ahejlsberg
    Member

    Nathan Shively-Sanders (@sandersn) already looked at this, I think there is a PR still open. The issue is that supporting indexed access (x["foo"]) as well as property access (x.foo) in control flow analysis has significant negative performance impact because we need to include many more nodes (i.e. all indexed access operations) in the control flow graph.

  4. sandersn commented on Aug 6, 2018

    @sandersn
    Member

    It was #10565. It might not be too hard to revive this PR and see how bad the slowdown is now, but I doubt it will be much different.

  5. RyanCavanaugh commented on Aug 6, 2018

    @RyanCavanaugh
    Member

    I'm surprised a syntactic check could be that expensive. There doesn't seem to be much going on in that PR that wasn't happening before and the number of indexed-by-string-literal property accesses in a given program shouldn't be that large?

  6. benneq commented on Aug 13, 2018

    @benneq

    Could you at least add this feature with some feature flag in tsconfig?

    I don't care if compilation becomes slower. But I do care about type errors. That's what this language is all about.

  7. sandersn commented on Aug 23, 2018

    @sandersn
    Member

    This should be fixed now.

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

Metadata

Metadata

Labels

BugA bug in TypeScript

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions