Skip to content

Instantly share code, notes, and snippets.

@sliekens
Last active May 27, 2018 15:19
Show Gist options
  • Save sliekens/6a756add830c919ad188dbbcbc60697f to your computer and use it in GitHub Desktop.
Save sliekens/6a756add830c919ad188dbbcbc60697f to your computer and use it in GitHub Desktop.
export class Hero {
id: number;
name: string;
superpower: Power;
friends: Hero[];
}
export class Power {
name: string;
}
// TODO: add conditional type for arrays (meaning when T[K] is an array) (requires TS 2.8, planned for NG 6.1)
// until then, simply do a manual cast from `Like<T[K][]>` to `Like<T[K]>[]`
export type Like<T> = {
[K in keyof T]: T[K] | Like<T[K]>
};
// This is how we used to write TypeScript
// Declare anonymous objects as Hero
const windstorm: Hero = {
id: 1,
name: 'Windstorm',
superpower: {
name: 'Storm manipulation'
},
friends: [
{ ... },
{ ... },
{ ... }
]
};
// Now you get the following intellisense
// windstorm: Hero
// windstorm.id: number;
// windstorm.name: string;
// windstorm.superpower: Power;
// windstorm.superpower.name: string;
// windstorm.friends: Hero[];
// but these are lies: windstorm's prototype is actually Object, not Hero
const isHero = windstorm instanceof Hero; // false
// same for superpower
const isPower = windstorm.superpower instanceof Power; // false
// same for friends
const areHeroes = windstorm.friends.every(friend => friend instanceof Hero); // false, false, false
// This is how I write TypeScript now
// Declare anonymous objects as Like<Hero> instead of Hero
const windstorm: Like<Hero> = {
id: 1,
name: 'Windstorm',
superpower: {
name: 'Storm manipulation'
},
friends: [
{ ... },
{ ... },
{ ... }
]
};
// Now you get the following intellisense
// windstorm: Like<Hero>
// windstorm.id: number;
// windstorm.name: string;
// windstorm.superpower: Power | Like<Power>;
// windstorm.superpower.name: string;
// windstorm.friends: Hero[] | Like<Hero[]>;
// instanceof Hero is still false, but this time you would have expected that, because intellisense
const isHero = windstorm instanceof Hero; // false, but not unexpected
// same for superpower
const isPower = windstorm.superpower instanceof Power; // false, but not unexpected
// same for friends
const areHeroes = windstorm.friends.every(friend => friend instanceof Hero); // false, false, false
// The only problem right now: TS <2.8 doesn't have conditional types
// ideally we would want `friends` to be typed like this:
// windstorm.friends: Hero[] | Like<Hero>[];
// this should be possible starting with TS 2.8 but I'm waiting for NG 6.1 to make it happen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment