Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
wagenet committed Nov 21, 2022
1 parent d4e7180 commit f7f643a
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 20 deletions.
1 change: 1 addition & 0 deletions node-tests/blueprints/helper-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';


const blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
const setupTestHooks = blueprintHelpers.setupTestHooks;
const emberNew = blueprintHelpers.emberNew;
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
108 changes: 108 additions & 0 deletions packages/@ember/object/type-tests/proxy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import Ember from 'ember';
import ObjectProxy from '@ember/object/proxy';
import { expectTypeOf } from 'expect-type';

interface Book {
title: string;
subtitle: string;
chapters: Array<{ title: string }>;
}

class DefaultProxy extends ObjectProxy {}
expectTypeOf(DefaultProxy.create().content).toEqualTypeOf<object | undefined>();

class BookProxy extends ObjectProxy<Book> {
private readonly baz = 'baz';

altTitle = 'Alt';

getTitle() {
return this.get('title');
}

getPropertiesTitleSubtitle() {
return this.getProperties('title', 'subtitle');
}
}

const book = BookProxy.create();
expectTypeOf(book.content).toEqualTypeOf<Book | undefined>();

// @ts-expect-error
book.get('unknownProperty');
expectTypeOf(book.get('title')).toEqualTypeOf<string | undefined>();
expectTypeOf(book.get('altTitle')).toBeString();
expectTypeOf(book.getTitle()).toEqualTypeOf<string | undefined>();

// @ts-expect-error
book.getProperties('title', 'unknownProperty');
expectTypeOf(book.getProperties('title', 'subtitle')).toEqualTypeOf<
Pick<Partial<Book>, 'title' | 'subtitle'>
>();
expectTypeOf(book.getPropertiesTitleSubtitle()).toEqualTypeOf<
Pick<Partial<Book>, 'title' | 'subtitle'>
>();
expectTypeOf(book.getProperties(['subtitle', 'chapters'])).toEqualTypeOf<
Pick<Partial<Book>, 'subtitle' | 'chapters'>
>();
// @ts-expect-error
book.getProperties(['title', 'unknownProperty']);

// @ts-expect-error
book.get('baz');

book.set('title', 'New');
// @ts-expect-error
book.set('title', 1);
book.set('altTitle', 'Alternate');
// @ts-expect-error
book.set('altTitle', 1);
book.setProperties({
title: 'new',
subtitle: 'and improved',
altTitle: 'Alternate2',
});
// @ts-expect-error
book.setProperties({ title: 1 });
// @ts-expect-error
book.setProperties({ altTitle: 1 });
// @ts-expect-error
book.setProperties({ invalid: true });

class Person extends Ember.Object {
firstName = 'Peter';

lastName = 'Wagenet';

@Ember.computed('firstName', 'lastName')
get fullName() {
return `${this.firstName} ${this.lastName}`;
}

set fullName(value: string) {
const [firstName, lastName] = value.split(' ');

Ember.set(this, 'firstName', firstName ?? '');
Ember.set(this, 'lastName', lastName ?? '');
}
}

class PersonProxy extends ObjectProxy<Person> {}

const person = PersonProxy.create();

expectTypeOf(person.get('firstName')).toEqualTypeOf<string | undefined>();
expectTypeOf(person.get('fullName')).toEqualTypeOf<string | undefined>();
expectTypeOf(person.set('fullName', 'John Doe')).toBeString();
// @ts-expect-error
person.set('fullName', 1);
// @ts-expect-error
person.set('invalid', true);
expectTypeOf(person.setProperties({ fullName: 'John Doe' })).toEqualTypeOf<
Pick<PersonProxy & Person, 'fullName'>
>();
expectTypeOf(person.setProperties({ fullName: 'John Doe' }).fullName).toBeString();
// @ts-expect-error
person.setProperties({ fullName: 1 });
// @ts-expect-error
person.setProperties({ fullName: 'John Doe', invalid: true });
16 changes: 16 additions & 0 deletions type-tests/preview/@ember/component-test/capabilities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { capabilities } from '@ember/component';
import { expectTypeOf } from 'expect-type';

expectTypeOf(capabilities('3.13')).toMatchTypeOf<{
asyncLifecycleCallbacks?: boolean | undefined;
destructor?: boolean | undefined;
updateHook?: boolean | undefined;
}>();

capabilities('3.13', { asyncLifecycleCallbacks: true });
capabilities('3.4', { asyncLifecycleCallbacks: true });

// @ts-expect-error invalid capabilities
capabilities('3.13', { asyncLifecycleCallbacks: 1 });
// @ts-expect-error invalid verison
capabilities('3.12');
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { setComponentTemplate } from '@ember/component';
import type { TemplateFactory } from 'htmlbars-inline-precompile';
import { expectTypeOf } from 'expect-type';

// Good enough for testing
let factory = {} as TemplateFactory;

expectTypeOf(setComponentTemplate(factory, {})).toEqualTypeOf<object>();
12 changes: 0 additions & 12 deletions types/preview/@ember/application/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,16 +133,4 @@ declare module '@ember/application' {
* @deprecated Use `import { setOwner } from '@ember/owner';` instead.
*/
export function setOwner(object: object, owner: Owner): void;

/**
* Detects when a specific package of Ember (e.g. 'Ember.Application')
* has fully loaded and is available for extension.
*/
export function onLoad(name: string, callback: AnyFn): unknown;

/**
* Called when an Ember.js package (e.g Ember.Application) has finished
* loading. Triggers any callbacks registered for this event.
*/
export function runLoadHooks(name: string, object?: {}): unknown;
}
39 changes: 31 additions & 8 deletions types/preview/@ember/component/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,37 @@ declare module '@ember/component' {
object: T
): T;

/**
* Takes a component class and returns the template associated with the given component class,
* if any, or one of its superclasses, if any, or undefined if no template association was found.
*
* @param object the component object
* @return the template factory of the given component
*/
export function getComponentTemplate(obj: object): TemplateFactory | undefined;
/**
* Takes a component class and returns the template associated with the given component class,
* if any, or one of its superclasses, if any, or undefined if no template association was found.
*
* @param object the component object
* @return the template factory of the given component
*/
export function getComponentTemplate(obj: object): TemplateFactory | undefined;

export function setComponentTemplate(factory: TemplateFactory, obj: object): object;

interface ComponentCapabilitiesVersions {
'3.4': {
asyncLifecycleCallbacks?: boolean;
destructor?: boolean;
};

'3.13': {
asyncLifecycleCallbacks?: boolean;
destructor?: boolean;
updateHook?: boolean;
};
}

interface ComponentCapabilities extends Capabilities {
asyncLifeCycleCallbacks: boolean;
destructor: boolean;
updateHook: boolean;
}

export function capabilities<Version extends keyof ComponentCapabilitiesVersions>(managerAPI: Version, options?: ComponentCapabilitiesVersions[Version]): ComponentCapabilities;

// In normal TypeScript, these built-in components are essentially opaque tokens
// that just need to be importable. Declaring them with unique interfaces
Expand Down

0 comments on commit f7f643a

Please sign in to comment.