Created
July 12, 2018 21:55
-
-
Save pcardune/90ab72d85d6c1d7b7b429ac1c3c7e99f to your computer and use it in GitHub Desktop.
Example of some complicated typescript typings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cloneable<T extends object> { | |
protected readonly data: T; | |
public static kind: string; | |
protected constructor(data: T) { | |
this.data = data; | |
} | |
static create<T extends object>(data: T) { | |
console.log('Creating a cloneable', this.kind); | |
return new this(data); | |
} | |
// this is ugly but works better than the previous. | |
static createWithType<T extends object, C extends Cloneable<T>>(data: T) { | |
console.log('Creating a cloneable', this.kind); | |
return <C>new this(data); | |
} | |
clone() { | |
return new (<typeof Cloneable>this.constructor)(this.data); | |
} | |
// This is ugly, but works better than the previous. Why is this necessary? | |
cloneWithType<C extends Cloneable<T>>(): C { | |
return <C>new (<typeof Cloneable>this.constructor)(this.data); | |
} | |
} | |
interface PersonData { | |
name: string; | |
} | |
class Person extends Cloneable<PersonData> { | |
static kind = 'Person'; | |
getName() { | |
return this.data.name; | |
} | |
} | |
// Why doesn't this just work? | |
// Type 'Cloneable<{ name: string; }>' is not assignable to type 'Person'. | |
// Property 'getName' is missing in type 'Cloneable<{ name: string; }>'. | |
const paul: Person = Person.create({ name: 'Paul' }); | |
// This is one way to fix it, but it's ugly. | |
const christophe: Person = Person.createWithType<PersonData, Person>({ | |
name: 'Christophe' | |
}); | |
// Why doesn't this just work? | |
// Type 'Cloneable<PersonData>' is not assignable to type 'Person'. | |
// Property 'getName' is missing in type 'Cloneable<PersonData>'. | |
const paul2: Person = paul.clone(); | |
// This seems to work but makes the cloneWithType definition quite complicated. | |
const christophe2: Person = christophe.cloneWithType(); | |
console.log(paul.getName()); | |
console.log(paul2.getName()); | |
console.log(christophe.getName()); | |
console.log(christophe2.getName()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The
create
issue is a common problem: microsoft/TypeScript#5863You probably just have to do
const paul = <Person>Person.create({ name: 'Paul' });
For the clone maybe something like this would work?