2021-05-25 11:16:01 +00:00
|
|
|
interface Props {
|
|
|
|
name: string
|
|
|
|
}
|
|
|
|
|
|
|
|
interface Core {
|
|
|
|
id: string
|
|
|
|
}
|
|
|
|
|
|
|
|
interface Instance extends Props, Core {}
|
|
|
|
|
|
|
|
const defaults: Props = {
|
2021-05-29 10:12:28 +00:00
|
|
|
name: 'Spot',
|
2021-05-25 11:16:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const core: Core = {
|
2021-05-29 10:12:28 +00:00
|
|
|
id: '0',
|
2021-05-25 11:16:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class ClassInstance<T extends object = {}> implements Instance {
|
2021-05-29 10:12:28 +00:00
|
|
|
id = '0'
|
|
|
|
name = 'Spot'
|
2021-05-25 11:16:01 +00:00
|
|
|
|
|
|
|
constructor(
|
|
|
|
props: Partial<Props> &
|
|
|
|
{ [K in keyof T]: K extends keyof Core ? never : T[K] }
|
|
|
|
) {
|
|
|
|
Object.assign(this, props)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
interface InstanceConstructor {
|
|
|
|
new <T extends object = {}>(
|
|
|
|
props: Partial<Props> &
|
|
|
|
{ [K in keyof T]: K extends keyof Core ? never : T[K] }
|
|
|
|
): Instance
|
|
|
|
}
|
|
|
|
|
|
|
|
function makeInstance<T extends object = {}>(
|
|
|
|
props: Partial<Props> &
|
|
|
|
{ [K in keyof T]: K extends keyof Core ? never : T[K] } &
|
|
|
|
ThisType<ClassInstance>
|
|
|
|
) {
|
|
|
|
return new ClassInstance<T>({ ...defaults, ...props, ...core })
|
|
|
|
}
|
|
|
|
|
|
|
|
function getInstance<T extends object = {}>(
|
|
|
|
props: Partial<Props> &
|
|
|
|
{ [K in keyof T]: K extends keyof Core ? never : T[K] }
|
|
|
|
) {
|
|
|
|
return { ...defaults, ...props, ...core }
|
|
|
|
}
|
|
|
|
|
|
|
|
const instance = getInstance({
|
2021-05-29 10:12:28 +00:00
|
|
|
name: 'Steve',
|
2021-05-25 11:16:01 +00:00
|
|
|
age: 93,
|
|
|
|
wag(this: Instance) {
|
|
|
|
return this.name
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
interface AnimalProps {
|
|
|
|
name: string
|
|
|
|
greet(this: Animal, name: string): string
|
|
|
|
}
|
|
|
|
|
|
|
|
interface AnimalCore {
|
|
|
|
id: string
|
|
|
|
sleep(this: Animal): void
|
|
|
|
}
|
|
|
|
|
|
|
|
interface Animal extends AnimalProps, AnimalCore {}
|
|
|
|
|
|
|
|
const getAnimal = <T extends object>(
|
|
|
|
props: Partial<AnimalProps> &
|
|
|
|
{ [K in keyof T]: K extends keyof AnimalCore ? never : T[K] }
|
|
|
|
): Animal & T => {
|
|
|
|
return {
|
|
|
|
// Defaults
|
2021-05-29 10:12:28 +00:00
|
|
|
name: 'Animal',
|
2021-05-25 11:16:01 +00:00
|
|
|
greet(name) {
|
2021-05-29 10:12:28 +00:00
|
|
|
return 'Hey ' + name
|
2021-05-25 11:16:01 +00:00
|
|
|
},
|
|
|
|
// Overrides
|
|
|
|
...props,
|
|
|
|
// Core
|
2021-05-29 10:12:28 +00:00
|
|
|
id: 'hi',
|
2021-05-25 11:16:01 +00:00
|
|
|
sleep() {},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const dog = getAnimal({
|
2021-05-29 10:12:28 +00:00
|
|
|
name: 'doggo',
|
2021-05-25 11:16:01 +00:00
|
|
|
greet(name) {
|
2021-05-29 10:12:28 +00:00
|
|
|
return 'Woof ' + this.name
|
2021-05-25 11:16:01 +00:00
|
|
|
},
|
|
|
|
wag() {
|
2021-05-29 10:12:28 +00:00
|
|
|
return 'wagging...'
|
2021-05-25 11:16:01 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2021-05-29 10:12:28 +00:00
|
|
|
dog.greet('steve')
|
2021-05-25 11:16:01 +00:00
|
|
|
dog.wag()
|
|
|
|
dog.sleep()
|
|
|
|
|
|
|
|
class ShapeTest {}
|
|
|
|
|
|
|
|
const shapeTest = new ShapeTest()
|
|
|
|
|
|
|
|
export default shapeTest
|
|
|
|
|
|
|
|
type Greet = (name: string) => string
|
|
|
|
|
|
|
|
const greet: Greet = (name: string | number) => {
|
2021-05-29 10:12:28 +00:00
|
|
|
return 'hello ' + name
|
2021-05-25 11:16:01 +00:00
|
|
|
}
|