Skip to content

variable assignation types fails for complex types inside array #26674

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

Closed
ganeshkbhat opened this issue Aug 25, 2018 · 2 comments
Closed

variable assignation types fails for complex types inside array #26674

ganeshkbhat opened this issue Aug 25, 2018 · 2 comments

Comments

@ganeshkbhat
Copy link

ganeshkbhat commented Aug 25, 2018

TypeScript Version: 3.0.1

Search Terms: Advanced Tyoes, Array Types Assignation, Multiple Types Array

Code

// Interfaces
export interface LinkObject {
    label: string;
    link?: string | undefined;
    method: string;
}

export interface Links {
    type: string;
    data: LinkObject;
}

export interface GroupObject {
    label: string;
    children?: LinkObject[] | undefined;
}

export interface Group {
    type: string;
    data: GroupObject | LinkObject;
}
// Code
import { Group, LinkObject, GroupObject, Links } from './interface';

var testers: LinkObject = { type: 'link', data: { label: 'Link 1', link: 'http://localhost:9000/apijhdkjdflkjfdlflkfglkflkflkgf', method: '' } };
var testers2: GroupObject = {
  type: 'group', data: {
    label: 'Group 1', children: [
      { label: 'Link 3', link: 'http://localhost:9000/apijhdkjdflkjfdlflkfglkflkflkgf', method: '' },
      { label: 'Link 4', link: '#', method: '' }
    ]
  }
}
var groupLinksObject: Group[] = [
  { type: 'link', data: { label: 'Link 1', link: 'http://localhost:9000/apijhdkjdflkjfdlflkfglkflkflkgf', method: '' } },
  {
    type: 'group', data: {
      label: 'Group 1', children: [
        { label: 'Link 3', link: 'http://localhost:9000/apijhdkjdflkjfdlflkfglkflkflkgf', method: '' },
        { label: 'Link 4', link: '#', method: '' }
      ]
    }
  },
  { type: 'link', data: { label: 'Link 1', link: '#', method: '' } }
];

Expected behavior:
Type should be allowed for Array

Actual behavior:
Throws error saying type not assignable and a property link/children not available in subtype of the interface

error TS2339: Property 'link' does not exist on type 'LinkObject | GroupObject'.
  Property 'link' does not exist on type 'GroupObject'
error TS2339: Property 'children' does not exist on type 'LinkObject | GroupObject'.
  Property 'children' does not exist on type 'LinkObject'

Seems duplicate of following:
#26673

Related Issues:
All assignation types failed

export interface GroupObject {
    label: string;
    children?: LinkObject[];
}

export interface GroupObject {
    label: string;
    children?: LinkObject[] | undefined;
}

export interface GroupObject {
    label: string;
    children: LinkObject[] | undefined;
}
@dizys
Copy link

dizys commented Aug 25, 2018

You probably miss the point of #26673 , whereas the behavior is totally unexpected and differs from bar to this.bar when they are the same thing.

In your case, I believe this is how TypeScript works. Giving type property's type 'string' won't help TypeScript do better inference about data at all. And the intention of your code, honestly, is super confusing.

Maybe a better practice, see if this is what you want to achieve:

export interface Link {
  type: 'link';
  label: string;
  url?: string | undefined;
}

export interface Group {
  type: 'group';
  label: string;
  children: Item[] | undefined;
}

export type Item = Group | Link;

export type Index = Item[];

const HomeIndex: Index = [
  { type: 'link', label: 'Home', url: '/' },
  {
    type: 'group', label: 'Forum', children: [
      { type: 'link', label: 'Topics', url: '/forum/topics/' },
      { type: 'link', label: 'Trending', url: '/forum/trending/' },
      { type: 'link', label: 'Search', url: '/forum/search/' },
    ]
  },
  { type: 'link', label: 'Documents', url: '/documents' },
  { type: 'link', label: 'Downloads', url: '/downloads'},
];

@ganeshkbhat
Copy link
Author

ganeshkbhat commented Aug 25, 2018

Ok great got it. It allowed me to work with nested typed interfaces after defining them as types. This is what I was trying to achieve:

  export interface Links {
    type: string;
    data: LinkType | GroupType;
  }

I did not notice this changed. I was able to use this before not sure what version of ts. This is what I did :

export interface Link {
    label: string;
    link?: string | undefined;
    method?: string;
  }
  export type LinkType = Link;
  export interface Group {
    label: string;
    children?: LinkType[] | undefined;
  }
  export type GroupType = Group;
  export type Links = {
    type: string;
    data: LinkType | GroupType;
  }

  export type Index = Links[];

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

2 participants