class Foo extends Ember.Object.extend({
a: Ember.computed({
get() { return ''; },
set(key: string, newVal: string) { return ''; }
})
}) {
b = 5;
baz() {
let y = this.b; // $ExpectType number
let z = this.a; // $ExpectType ComputedProperty<string, string>
this.b = 10;
this.get('b').toFixed(4); // $ExpectType string
this.set('a', 'abc').split(','); // 馃挜 $ExpectType string[]
this.set('b', 10).toFixed(4); // 馃挜 $ExpectType string
this.setProperties({ b: 11 }); // 馃挜
// this.setProperties({ b: '11' }); // 馃挜 $ExpectError
this.setProperties({ // 馃挜
a: 'def',
b: 11
});
}
}
I expected to be able to set properties on my ember objects with no type errors
This has something to do with the new UnwrapComputedPropertySetters stuff breaking when combined with pulling types off of this. I spent several hours digging into this, and feel like I'm at a 1 !== 1 situation.
@dfreeman @dwickern @jamescdavis If you could poke at this sometime soon, I would love to find a near-term solution that doesn't involve weakening the types -- I just have run out of time trying to figure it out.
Until we can arrive at some root cause and fix it, I'll add the failing test case above and relax the types around this.set a bit, so we're no longer blocking anyone.
It's clear, one factor that contributed to this problem making it into a release is very thin test coverage in some areas. Part of my debugging process involved creating dozens of new tests -- particularly around some of the tricker areas of the types (computed properties, Ember.Object.create, Ember.Object.extend, the Observable interface, etc...`)
The PR related to this issue was just merged. This means we no longer have type safety when using set() with settable computed properties.
I spent a little time on this this evening and I think either I have a fundamental misunderstanding of some aspect of the type system or there's a bug in the compiler around this types. I would expect this code to typecheck, but it doesn't:
declare const brand: unique symbol;
type Wrapped<T> = { [brand]: T };
type Unwrap<T> = T extends Wrapped<infer U> ? U : T;
declare function set<T, K extends keyof T>(obj: T, key: K, value: Unwrap<T[K]>);
class Foo {
prop: Wrapped<string>;
method() {
// Argument of type '"hi"' is not assignable to parameter
// of type 'Unwrap<this["prop"]>'.
set(this, 'prop', 'hi');
}
}
// Works as expected
set(new Foo(), 'prop', 'hi');
If I understand the situation correctly, it's not only:
we no longer have type safety when using set() with settable computed properties.
Rather, we no longer have type safety when using set at all, even if no computed properties are involved:
class Example extends Controller {
title = "hello";
anAction() {
this.set('title', 42); // <- should be a type error: found number, expected string
}
}
Removing this line fixes my example, but I don't know what else it would break.
@ef4 which version of the types, and which version of typescript are you using? this and keyof this are areas of the types that are _extremely_ sensitive to breaking compiler changes -- I need to dig in and figure out if this is a new problem
@types/ember 3.1.0 and typescript 3.5.2.
Most helpful comment
This has something to do with the new
UnwrapComputedPropertySettersstuff breaking when combined with pulling types off ofthis. I spent several hours digging into this, and feel like I'm at a1 !== 1situation.@dfreeman @dwickern @jamescdavis If you could poke at this sometime soon, I would love to find a near-term solution that doesn't involve weakening the types -- I just have run out of time trying to figure it out.
Until we can arrive at some root cause and fix it, I'll add the failing test case above and relax the types around
this.seta bit, so we're no longer blocking anyone.It's clear, one factor that contributed to this problem making it into a release is very thin test coverage in some areas. Part of my debugging process involved creating dozens of new tests -- particularly around some of the tricker areas of the types (computed properties,
Ember.Object.create,Ember.Object.extend, theObservableinterface, etc...`)