question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ember 3.13+ and TypeScript: Computed properties don't work as expected

See original GitHub issue

Hi all,

we are currently using Ember 3.12 with ember-cli-typescript and would like to upgrade to Ember 3.14+, but as of Ember 3.13 wie experience problems with this upgrade. In https://github.com/emberjs/ember.js/issues/18614, @pzuraq gave us a very helpful hint that the problem could be ember-cli-typescript or TypeScript itself.

We hope that you can help us.

Please paste the output of ember -v here

ember-cli: 3.13.2
node: 12.13.1
os: win32 x64

Please paste the output of tsc -v here

Version 3.7.3

Please paste the version of ember-cli-typescript and ember-cli-typescript-blueprints here

ember-cli-typescript@3.1.2
ember-cli-typescript-blueprints@3.0.0

Please paste your tsconfig.json and tslint.json or eslint.json (if applicable) below

My tsconfig.json
{
  "compilerOptions": {
    "target": "es2017",
    "allowJs": true,
    "moduleResolution": "node",
    "allowSyntheticDefaultImports": true,
    "noImplicitAny": true,
    "noImplicitThis": true,
    "alwaysStrict": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noEmitOnError": false,
    "noEmit": true,
    "inlineSourceMap": true,
    "inlineSources": true,
    "baseUrl": ".",
    "module": "es6",
    "experimentalDecorators": true,
    "paths": {
      "test-model-reactivity/tests/*": [
        "tests/*"
      ],
      "test-model-reactivity/*": [
        "app/*"
      ],
      "*": [
        "types/*"
      ]
    }
  },
  "include": [
    "app/**/*",
    "tests/**/*",
    "types/**/*"
  ]
}

What are instructions we can follow to reproduce the issue?

ember new test-model-reactivity
ember install ember-cli-typescript
Reproduction Case
ember g route application
ember g controller application

Add the following lines

// routes/application.ts
import Route from "@ember/routing/route";
import RSVP from "rsvp";

export class Example {
  constructor(public value: string) { }
}

export class ApplicationModel {
  constructor(public example: Example) { }
}

export default class Application extends Route {
  model(_params: {}, _transition: any): RSVP.Promise<ApplicationModel> {
    return RSVP.resolve(new ApplicationModel(new Example("test")));
  }
}
// controllers/application.ts
import Controller from "@ember/controller";
import {ApplicationModel} from "test-model-reactivity/routes/application";
import {action, computed, set} from "@ember/object";

export default class Application extends Controller {

  model!: ApplicationModel;

  @computed("model.example.value")
  get value() {
    return this.model.example.value;
  }

  @action
  changeExampleValue() {
    set(this.model.example, "value", String(Math.random()));
  }
}

// DO NOT DELETE: this is how TypeScript knows how to look up your controllers.
declare module "@ember/controller" {
  interface Registry {
    "application": Application;
  }
}
{{! templates/application.hbs }}
<button {{on "click" this.changeExampleValue}}>
  {{this.value}}
</button>

Now about that bug. What did you expect to see?

The template should update after the button was clicked.

What happened instead?

The template is not updated because the computed property value is not executed.

Hint

The JavaScript version of the example above works like expected, only the TypeScript version has this problems.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
chriskrychocommented, Dec 16, 2019

Yep, that’s a known issue which will have a release with the fix shortly.

1reaction
chriskrychocommented, Dec 15, 2019

I’ll make sure we cover this failure case more thoroughly in the updated docs, but this is in fact expected behavior (and doesn’t require changing the base types). The problem is what this transpiles to:

class Foo {
  bar;
}

The resulting output per the spec is (basically):

class Foo {
  constructor() {
    defineProperty(this, 'bar', void 0);
  }
}

TS has basically “overloaded” the meaning of a property declaration on a class like this, by making it where you declare the type as well. This is what you found in your inspection of the compiled output: even if the declaration is bar: string rather than bar;, it has the same output. The TypeScript team is aware of this issue, and in fact TypeScript 3.7 includes a new declare syntax to support this exact use case. With that new syntax, you’d write it like this:

class MyController extends Controller {
  declare model!: ApplicationModel;
  // ...
}

I’m not sure what changed between 3.12 and 3.13; it’s possible an ordering difference around setupController and the instantiation of the Controller was introduced in certain edge cases. ember-cli-typescript and our compilation pipeline’s handling of this specific scenario haven’t changed in quite some time, so while it’s not impossible that we’re doing something wrong, I’d be much more suspicious of changes in the framework.

cc. @rwjblue @pzuraq @chancancode – the only thing I can think of here that would be relevant in the 3.12→3.13 is the prep work that was done to support @model in 3.14?

Read more comments on GitHub >

github_iconTop Results From Across the Web

What is the proper way to write a computed property using ...
1 Answer 1 · I'm a little confused here, @chris-krycho. It seems that your version of the cp code and my version are...
Read more >
Computed properties: What am I missing? - General
Hi,. The behavior of ember computed properties always suprises me and I would like to have a better understand of it. (I am...
Read more >
Awesome Ember.js
ember -local-storage - The addon provides a storage for computed property that returns a proxy and persists the changes to localStorage or sessionStorage....
Read more >
Moving from React to Ember 2020 : r/emberjs
Due to the Octane work (I guess) Ember has lost the capacity of two-way binding to older components' computed properties, and this was...
Read more >
Computed Properties - ember-cli-typescript
Note that it is impossible for @computed to know whether the keys you pass to it are allowed or not. Migrating to Octane...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found