Sunday, May 5, 2024
HomeJavaScriptAsserting the Official TypeScript Varieties Public Preview

Asserting the Official TypeScript Varieties Public Preview


As of ember-source@4.8.0-beta.2, Ember is delivery a public preview of our official TypeScript help for the framework itself. That is the following step in implementing RFC 0724: Official TypeScript Help and RFC 0800: TypeScript Adoption Plan. Anybody utilizing TypeScript with Ember 4.8.0 Beta 2 or later can choose into utilizing these preview sorts by eradicating the corresponding @sorts packages and including the next import in your sorts/<your app>/index.d.ts file:

import 'ember-source/sorts';
import 'ember-source/sorts/preview';

This may set your app as much as begin utilizing Ember’s preview sorts now and to mechanically profit as we stabilize our sorts incrementally over the releases forward. You will not should do something besides add these as soon as after which improve your app in your regular improve cadence!

Word that there are some important adjustments to those sorts in comparison with the categories as they exist on DefinitelyTyped immediately. All public API stays supported, however in step with RFC 0800, we deliberately present solely minimal help for Ember Traditional APIs round class definitions. Accordingly, it is best to migrate to native lessons earlier than making an attempt to undertake these sorts when you have not already carried out so!

The remainder of this submit is damaged into 4 sections:

For those who’re curious in regards to the particulars of how this strategy to publishing TypeScript sorts for Ember works, take a look at the PR which launched help!

How the preview interval will work

There are two type-only modules you import: 'ember-source/sorts' and 'ember-source/sorts/preview'. These symbolize the secure and preview sorts respectively. At the beginning of the preview interval, there’s nothing in any respect within the secure module: all the categories are within the preview module.

The important thing distinction between the secure and preview sorts is: our secure sorts should be generated from Ember’s personal TypeScript supply code, whereas the preview sorts are hand-written sort definitions. The hand-written definitions match up intently to the precise code, however small gaps are inevitable. Varieties revealed immediately from Ember’s personal supply code won’t have that drawback!

Over the course of the preview interval, we might be doing two issues:

  1. We might be fixing bugs in these sorts as they’re recognized, and releasing bug repair releases the identical manner we’d for runtime errors. (This would be the new regular for Ember: fixes to sorts are precisely like fixes to runtime errors, as a result of each are bugs!)

  2. We might be engaged on Ember’s construct infrastructure and the construction of its internals to make it potential to publish sorts immediately from the supply, as a substitute of utilizing hand-authored sorts. These are the categories which might be uncovered by way of the import 'ember-source/sorts'; assertion.

As soon as we’re totally lower over to publishing sorts from Ember’s supply code, we are going to declare them “secure” and subsequently topic to Ember’s regular SemVer coverage. For particulars on how we’re dealing with SemVer for TypeScript, take a look at the related part of RFC 0800 and the Semantic Versioning for TypeScript spec we authored and comply with. We’ll even be updating the web site with these particulars within the subsequent few weeks.

We’ll make a greatest effort to keep away from breaking adjustments within the sorts through the preview interval, however the transition to the secure sorts will inevitably contain many bug fixes which can really feel like breaking adjustments!

Additionally, on condition that these are preview sorts, we are going to proceed to keep up the categories on DefinitelyTyped till we stabilize these. For those who attempt them out and hit points you can not resolve, that’s completely nice! There are two issues we predict it is best to do in that case:

  1. File a difficulty on the ember.js repo with a report in regards to the challenge you had.
  2. Swap again to the @sorts packages!

We’ll ensure that there aren’t any blocking bugs earlier than stabilizing.

Migrating from DefinitelyTyped

This part solely applies if you’re an present Ember TypeScript person who has been utilizing the @sorts packages from DefinitelyTyped. For those who’re making an attempt out TypeScript for the primary time now, you may skip it!

There are 4 steps concerned in switching from the prevailing sorts revealed on DefinitelyTyped to those preview sorts.

  1. Take away the next packages out of your package deal.json:

    • @sorts/ember
    • @sorts/ember__application
    • @sorts/ember__array
    • @sorts/ember__component
    • @sorts/ember__controller
    • @sorts/ember__debug
    • @sorts/ember__destroyable
    • @sorts/ember__engine
    • @sorts/ember__error
    • @sorts/ember__helper
    • @sorts/ember__modifier
    • @sorts/ember__object
    • @sorts/ember__owner
    • @sorts/ember__polyfills
    • @sorts/ember__routing
    • @sorts/ember__runloop
    • @sorts/ember__service
    • @sorts/ember__string
    • @sorts/ember__template
    • @sorts/ember__test
    • @sorts/ember__utils
  2. Set up a model of ember-source better than 4.8.0-beta.2. You must choose the most recent beta of 4.8 or any secure model beginning with 4.8.0 as soon as it is out!

  3. Within the sorts/<your-app>/index.d.ts file generated for you mechanically by ember-cli-typescript, add the brand new imports as the primary objects within the file, and take away the array prototype extensions help from the file. With the defaults generated for you, the consequence would appear to be this:

    +import 'ember-source/sorts';
    +import 'ember-source/sorts/preview';
    -import Ember from 'ember';
    -
    -declare world {
    - // Prevents ESLint from "fixing" this by way of its auto-fix to show it into a sort
    - // alias (e.g. after operating any Ember CLI generator)
    - // eslint-disable-next-line @typescript-eslint/no-empty-interface
    - interface Array extends Ember.ArrayPrototypeExtensions {}
    - // interface Operate extends Ember.FunctionPrototypeExtensions {}
    -}
    
    export {};
  4. Account for the variations between the preview sorts and the definitions on DefinitelyTyped. These variations all fall into certainly one of these broad classes:

    • Fixes to issues within the present definitions.
    • Removing of our (poor!) help for Ember Traditional class options in favor of native lessons.
    • Modifications to sort registry dealing with
    • Removing of legacy (personal) routing APIs

Fixes to issues within the present definitions

For the preview sorts, we began by copying over the community-maintained sort definitions from DefinitelyTyped. We then up to date them to make use of extra sturdy sort testing instruments that DefinitelyTyped permits, which uncovered a bunch of bugs to repair. We additionally did a primary comparability of the categories we’re publishing with the corresponding sorts in Ember’s personal code, which has been written in TypeScript for years and received an enormous enchancment from @wagenet earlier this yr.

In consequence, you could discover some variations if you change over. In each case, these symbolize bug fixes, however we acknowledge they might contain some work!

Introducing a Resolver sort

The kinds on DefinitelyTyped provide a definition of Resolver from ember-resolver, which is the place most Ember customers get their resolver. Nevertheless, ember-resolver and different resolvers work as a result of they implement Ember’s contract for what a resolver is. A future RFC will introduce a public sort import for this. (It was missed through the work on RFC 0821 as a result of the kind presently does not come from Ember!)

For now, the kind exists at @ember/-internals/resolver, and is launched to be type-compatible with the kind for ember-resolver on DefinitelyTyped. (See this challenge for a difficulty monitoring publishing sorts from ember-resolver, which is probably going gated on a public sort import from Ember, however till we ship secure sorts, could be managed by way of cautious sorts work on DefinitelyTyped.)

Eradicating help for Array prototype extensions

This work additionally uncovered a variety of errors within the present sorts, particularly round Array prototype extensions. In consequence, these sorts don’t help Array prototype extensions, and it’s unlikely that future work will be capable of add that help. (The help offered by way of the categories on DefinitelyTyped solely labored as a result of the categories have been outlined incorrectly, leading to a wide range of sorts of unsafety.)

Notably, Array prototype extensions are being deprecated, so shifting off of them is figure you will want to do anyway.

Ember Traditional help

As laid out in RFC 0800, there are additionally a variety of breaking adjustments from the categories in DefinitelyTyped concerning help for Ember Traditional options:

Per the version help coverage, we are going to present minimal help for Ember Traditional options:

  • Ember’s traditional class system: we are going to present minimal definitions for the .create(), .lengthen(), .reopen(), .reopenClass(), strategies, which make no try to make use of them to truly replace the varieties of the objects they modify.…

  • Ember’s get and set helpers: we won’t present sorts to make get and set type-safe past property lookups on objects—i.e. no help for nested path lookups.…

  • Traditional computed property dealing with: we won’t present “secure” sorts for the traditional type of computed properties.

Ember’s traditional class system

The definitions on DefinitelyTyped tried to make .create() and .lengthen() truly create up to date sorts, and tried to make .create(), .lengthen(), .reopen(), and .reopenClass() have the proper sort for this inside their our bodies. These have been all the time extraordinarily fragile and principally didn’t work. Since Ember 3.6, Ember customers have been ready to make use of native lessons as a substitute of Ember’s traditional class system, and this has been the really helpful manner of writing Ember code for the reason that launch of the Octane version in Ember 3.15.

Within the preview sorts, these strategies are current and are secure to make use of since they’re nonetheless a part of Ember’s public API. Nevertheless, .create() and .lengthen() don’t create new sorts. The .create() methodology does nonetheless examine that the values you move match these outlined on the category physique, however the sorts don’t try to make this have the fitting sort inside the our bodies of .create(), .lengthen(), .reopen(), or .reopenClass().

Emigrate, it is best to:

  • Convert all your personal traditional lessons to native lessons.
  • Eradicate your use of mixins.

(Most Ember TypeScript customers have already carried out this, as a result of these labored so poorly with TypeScript.)

The .create() name can all the time get replaced with a standard class definition in JavaScript. For every of the others, it’s also possible to use declaration merging to symbolize the conduct of the tactic in query.

.lengthen()

For the case the place you might be solely defining a brand new class, convert to a local class as a substitute. Nevertheless, when you have code which nonetheless depends on mixins like Evented, you may symbolize it utilizing interface merging like this:

import EmberObject from '@ember/object';
import Evented from '@ember/object/evented';
import sort Proprietor from '@ember/proprietor';

// A local class which nonetheless applies the Evented mixin
class ExtendsDemo extends EmberObject.lengthen(Evented) {
  moreStuff = true;

  constructor(proprietor: Proprietor) {
    tremendous(proprietor);
    this.on('customized', this, 'boundMethod');
  }

  willDestroy(): void {
    this.off('customized', this, 'boundMethod');
  }

  boundMethod = () => {
    alert('do one thing');
  };
}

// Make that work for the *sort* by merging the kind of the category
// (`interface ExtendsDemo`) with the kind of the mixin (`Evented`)
interface ExtendsDemo extends Evented {}

const occasion = ExtendsDemo.create({
  moreStuff: false,
});

occasion.set off('customized');

Word: you’ll have to disable the @typescript-eslint/no-empty-interface ESLint rule for this.

You are able to do the identical to your personal mixins whereas transitioning by defining an interface which represents the kind of the mixin:

import Mixin from '@ember/object/mixin';

// Creates the runtime mixin code
const Alertable = Mixin.create({
  alert(worth: string) {
    alert(`The worth is ${worth}`);
  }
})

// Creates the kind for TypeScript to see.
interface Alertable extends Mixin {
  alert(worth: string): void;
}

// Exports them as a single identify in each worth and kind house.
export default Alertable;
.reopen()

Typically, .reopen() is an antipattern, as a result of it makes it very exhausting to know the place a given a part of a category’ state or conduct lives, and it is best to transfer away from it! You must choose to delegate to a category as a substitute of dynamically including conduct to it, each for maintainability and for efficiency. Nevertheless, for the transition, you may symbolize it utilizing interface merging.

import EmberObject from '@ember/object';

class Foo extends EmberObject {
  someProp = 123;
}

// That is what makes the change work at runtime...
Foo.reopen({
  further: 'hey',
});

// ...whereas that is what makes it seen to the kind system.
interface Foo {
  further: string;
}

// Now when calling `Foo.create`, or when working with an occasion of the
// class, each `someProp` and `further` might be checked.
const occasion = Foo.create({
  someProp: 456,
  further: 'goodbye',
});
.reopenClass()

As with .reopen(), using .reopenClass() is an antipattern it is best to transfer away from over time, preferring to make use of common capabilities in module scope or regular static strategies on native lessons. Within the meantime, you need to use namespace merging to symbolize the way it works:

import EmberObject from '@ember/object';

class Foo extends EmberObject {
  static someStatic = true;
}

// This provides the tactic to the Foo class at runtime...
Foo.reopenClass({
  anotherStatic(): string {
    return 'hey';
  },
});

// ...and this makes it seen to TypeScript as a static methodology.
declare namespace Foo {
  export perform anotherStatic(): string;
}

if (Foo.someStatic) {
  Foo.anotherStatic().size;
}

Word: you’ll have to disable the @typescript-eslint/no-namespace ESLint rule for this.

Kind registries

These sorts, as a reasonably direct extraction from DefinitelyTyped, presently preserve the service and controller sort registries. Given the shortage of help for traditional computed properties, that are the primary option to benefit from these at current, it’s pretty possible some or all of those might be eliminated earlier than stabilizing the categories. The key remaining use case is type-safe lookup utilizing the Proprietor.lookup APIs, so when you have ideas on that, please attain out in #dev-typescript.

Legacy routing sort areas

In keeping with RFC 0821: Public API for Kind-Solely Imports, this PR additionally removes help for importing the categories for Transition, RouteInfo, and RouteInfoWithMetadata from the personal areas that DefinitelyTyped presently helps for backwards compatibility. Customers might want to migrate to utilizing the proper import paths when switching to make use of these imports.

  • import Transition from '@ember/routing/-private/transition'import Transition from '@ember/routing/transition'
  • import RouteInfo from '@ember/routing/-private/route-info'import RouteInfo from '@ember/routing/route-info'
  • import { RouteInfoWithMetadata } from '@ember/routing/-private/route-info-with-metadata'import { RouteInfoWithMetadata } from '@ember/routing/route-info'

New TypeScript customers

This part solely applies if you’re making an attempt out the categories for the primary time!

For the second, one of the simplest ways to get began with these sorts is to put in ember-cli-typescript and use its mills, then take away a number of what it does. We might be fixing this within the weeks forward!

Right here’s the method as of immediately:

  1. Arrange ember-cli-typescript by operating ember set up ember-cli-typescript.

  2. Take away the next newly-added packages out of your package deal.json:

    • @sorts/ember
    • @sorts/ember__application
    • @sorts/ember__array
    • @sorts/ember__component
    • @sorts/ember__controller
    • @sorts/ember__debug
    • @sorts/ember__destroyable
    • @sorts/ember__engine
    • @sorts/ember__error
    • @sorts/ember__helper
    • @sorts/ember__modifier
    • @sorts/ember__object
    • @sorts/ember__owner
    • @sorts/ember__polyfills
    • @sorts/ember__routing
    • @sorts/ember__runloop
    • @sorts/ember__service
    • @sorts/ember__string
    • @sorts/ember__template
    • @sorts/ember__test
    • @sorts/ember__utils
  3. Set up a model of ember-source better than 4.8.0-beta.2. You must choose the most recent beta of 4.8 or any secure model beginning with 4.8.0 as soon as it is out!

  4. Within the sorts/<your-app>/index.d.ts file generated for you mechanically by ember-cli-typescript, add the brand new imports as the primary objects within the file, and take away the array prototype extensions help from the file. With the defaults generated for you, the consequence would appear to be this:

    +import 'ember-source/sorts';
    +import 'ember-source/sorts/preview';
    -import Ember from 'ember';
    -
    -declare world {
    - // Prevents ESLint from "fixing" this by way of its auto-fix to show it into a sort
    - // alias (e.g. after operating any Ember CLI generator)
    - // eslint-disable-next-line @typescript-eslint/no-empty-interface
    - interface Array extends Ember.ArrayPrototypeExtensions {}
    - // interface Operate extends Ember.FunctionPrototypeExtensions {}
    -}
    
    export {};

Identified points

The primary beta launch has the next recognized points (which we are going to repair through the beta interval):

  • The @sorts/ember-data packages will not be appropriate with these sorts, as a result of they assume the presence of most of the Ember Traditional sorts we eliminated on this migration. If you’re utilizing Ember Knowledge with TypeScript, you will want to attend for a future replace.
  • The import file for secure sorts doesn’t exist but, so TypeScript will warn you that there isn’t any sort for the module. We count on to repair this earlier than releasing 4.8.0-beta.3!

What’s subsequent on Ember’s highway to TypeScript?

Now that we’ve these preview sorts in place, we are able to start publishing sorts in a secure manner as quickly as our construct tooling for Ember itself helps it. As we accomplish that, increasingly the categories might be offered by the import 'ember-source/sorts'; import, and fewer from the import 'ember-source/sorts/preview'; import. That may largely be clear to you as an finish person. The place there are be small variations, we are going to notice them because it occurs!

We hope to progressively change over from these preview sorts to the secure sorts within the 4.9–4.11 timeframe—that’s, earlier than the 4.12 LTS candidate launch comes out. As all the time with software program, and particularly open supply software program, there aren’t any ensures, although!

We’re additionally engaged on a “quest” challenge for getting the remainder of RFC 0800 carried out. There are a lot of different core packages which must publish sorts for us to get all the best way to our purpose of getting first-class TypeScript help for the ecosystem. We might use your assist! For those who’d prefer to pitch in, take a look at the monitoring challenge and attain out in #dev-typescript on Discord!

In parallel, there are two different huge efforts in flight:

  1. The Ember TypeScript group is making regular progress on getting Glint to its 1.0 launch.

    • We lately shipped primary help for TypeScript challenge references, i.e. the --build command, and count on to complete that up by supporting --build --watch mode within the subsequent month or two.

    • We supported Framework Core group member emeritus @chadhietala in touchdown full help for GlimmerX in Glint.

    • We recognized a major refactor we are able to make which can allow us to give a lot higher sort errors and remove a variety of difficult edge circumstances. (For those who’ve hit the “Anticipated 3 arguments however received 2” error for an merchandise which solely has two arguments, it will repair that and a bunch of others as effectively!)

  2. The Ember Studying group is working intently with the Ember TypeScript group and to construct out help for TypeScript in our API docs and the Guides. The trouble is being led by a neighborhood member, @ttbach—and he or she might additionally use your assist, too! A lot of the work right here does not require TypeScript experience, solely the power to work on Node instruments, so it’s one other great place to leap in. Attain out to @thaobach in #dev-ember-learning if you need to contribute!

That’s it for now, however preserve your eyes open for additional weblog posts in regards to the TypeScript effort and different elements of Polaris!

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments