1

I'm trying to prototype-based programming with typescirpt and found that typescript has limited support for this. So I want to know if using typescript basically gives up the prototype-based programming paradigm?

Here is my demo code:

const Foo = {
  init (name: string) {
    this.name = name
    return this
  },
  getName(): string {
    return this.name
  }
}

const Bar = {
  init (name: string, label: string) {
    Foo.init.call(this, name)
    this.label = label
    return this
  },
  getLabel() {
    return this.label
  }
}
Object.setPrototypeOf(Bar, Foo)

const bar = <typeof Bar> Object.create(Bar)
bar.init('lisiur', 'javascript')
bar.getName()

And in the last line typescript complain that Property 'getName' does not exist on type '{ init(name: string, label: string): any; getLabel(): any; }'.ts(2339). Is there a way to fix it?


update:

In lib.d.ts, Object.create and Object.setPrototypeOf all miss necessary type declaration(they all return any). So is there a way to declare my own create and setPrototypeOf to achieve that?

9
  • Nope. Not at all. In fact, when TypeScript is transpiled back to JavaScript, prototypes are heavily used. But, I should add, if you go that direction you should expect to be using JavaScript syntax more heavily than TypeScript. Commented May 27, 2019 at 2:07
  • Why are you trying so hard to avoid constructors/class? This implements exactly the same thing, but in a much less convenient way. Commented May 27, 2019 at 2:09
  • Ry is correct. Why struggle with typescript at all if you are going to lose the primary advantage it provides: familiarity (from other paradigms). Commented May 27, 2019 at 2:11
  • Any JS file can be renamed to be a TS file and as long as the Javascript is valid so is the Typescript (but not vise versa). Commented May 27, 2019 at 2:14
  • You could do const bar = <typeof Bar & typeof Foo>Object.create(Bar) to solve your issue, but this might not be an issue if you use JavaScript classes as others have mentioned. Commented May 27, 2019 at 2:16

1 Answer 1

2

It is possible to create objects with the prototype paradigm, but TypeScript won't be able to infer their types. It is still possible to use typing but they have to be provided manually. An example:

interface FooBaseType {
  getName(): string
}

interface FooType extends FooBaseType {
  init(name: string): void
}

interface BarType extends FooBaseType {
  init(name: string, label: string): void
  getLabel(): string
}

const Foo = { /* … */ }
const Bar = { /* … */ }
Object.setPrototypeOf(Bar, Foo)

const bar = Object.create(Bar) as BarType // manually affects 'BarType'
bar.init('lisiur', 'javascript')
bar.getName()

… Or the same example, using inference from Foo and Bar:

const Foo = { /* … */ }
const Bar = { /* … */ }
Object.setPrototypeOf(Bar, Foo)

// Remove the following line with TypeScript 3.5
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>

type FooBaseType = Omit<typeof Foo, "init">
type FooType = FooBaseType & Pick<typeof Foo, "init">
type BarType = FooBaseType & typeof Bar

const bar = Object.create(Bar) as BarType // manually affects 'BarType'
bar.init('lisiur', 'javascript')
bar.getName()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.