Skip to content

Commit ad748e0

Browse files
committed
strictNullChecks/strictPropertyInitialization WIP
This PR focuses on unblocking `strictNullChecks` and `strictPropertyInitialization` in ecmascript.ts and calendar.ts. It's intended as a complement to @jens-ox's work to remove `GetIntrinsic`. This PR: * Enables strictNullChecks: true and strictPropertyInitialization: true in tsconfig.json. * Improves calendar.ts TS types (this was most of the work in this PR) * Removes all unnecessary use of `any` throughout the polyfill * Updates types of ecmascript.ts and fixes a number of type bugs * Refactors a few types in intl.ts * A handful of trivial type changes in other files (ecmascript.ts and calendar-ts were 95%+ of the work). I'm working on splitting out any runtime changes into separate PRs. Once those are split out, this PR should be ready to review.
1 parent 6119bbc commit ad748e0

9 files changed

+702
-494
lines changed

index.d.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -603,8 +603,9 @@ export namespace Temporal {
603603
readonly [Symbol.toStringTag]: 'Temporal.Instant';
604604
}
605605

606-
type EitherYearOrEraAndEraYear = { era: string; eraYear: number } | { year: number };
607-
type EitherMonthCodeOrMonthAndYear = (EitherYearOrEraAndEraYear & { month: number }) | { monthCode: string };
606+
type YearOrEraAndEraYear = { era: string; eraYear: number } | { year: number };
607+
type MonthCodeOrMonthAndYear = (YearOrEraAndEraYear & { month: number }) | { monthCode: string };
608+
type MonthOrMonthCode = { month: number } | { monthCode: string };
608609

609610
export interface CalendarProtocol {
610611
id?: string;
@@ -648,15 +649,15 @@ export namespace Temporal {
648649
date: Temporal.PlainDate | Temporal.PlainDateTime | Temporal.PlainYearMonth | PlainDateLike | string
649650
): boolean;
650651
dateFromFields(
651-
fields: EitherMonthCodeOrMonthAndYear & { day: number },
652+
fields: YearOrEraAndEraYear & MonthOrMonthCode & { day: number },
652653
options?: AssignmentOptions
653654
): Temporal.PlainDate;
654655
yearMonthFromFields(
655-
fields: EitherYearOrEraAndEraYear & ({ month: number } | { monthCode: string }),
656+
fields: YearOrEraAndEraYear & MonthOrMonthCode,
656657
options?: AssignmentOptions
657658
): Temporal.PlainYearMonth;
658659
monthDayFromFields(
659-
fields: EitherMonthCodeOrMonthAndYear & { day: number },
660+
fields: MonthCodeOrMonthAndYear & { day: number },
660661
options?: AssignmentOptions
661662
): Temporal.PlainMonthDay;
662663
dateAdd(
@@ -726,15 +727,15 @@ export namespace Temporal {
726727
date: Temporal.PlainDate | Temporal.PlainDateTime | Temporal.PlainYearMonth | PlainDateLike | string
727728
): boolean;
728729
dateFromFields(
729-
fields: EitherMonthCodeOrMonthAndYear & { day: number },
730+
fields: YearOrEraAndEraYear & MonthOrMonthCode & { day: number },
730731
options?: AssignmentOptions
731732
): Temporal.PlainDate;
732733
yearMonthFromFields(
733-
fields: EitherYearOrEraAndEraYear & ({ month: number } | { monthCode: string }),
734+
fields: YearOrEraAndEraYear & MonthOrMonthCode,
734735
options?: AssignmentOptions
735736
): Temporal.PlainYearMonth;
736737
monthDayFromFields(
737-
fields: EitherMonthCodeOrMonthAndYear & { day: number },
738+
fields: MonthCodeOrMonthAndYear & { day: number },
738739
options?: AssignmentOptions
739740
): Temporal.PlainMonthDay;
740741
dateAdd(

lib/calendar.ts

Lines changed: 500 additions & 364 deletions
Large diffs are not rendered by default.

lib/ecmascript.ts

Lines changed: 167 additions & 90 deletions
Large diffs are not rendered by default.

lib/intl.ts

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,7 @@ import {
1616
TIME_ZONE
1717
} from './slots';
1818
import { Temporal, Intl } from '..';
19-
import {
20-
DateTimeFormatParams as Params,
21-
DateTimeFormatReturn as Return,
22-
InstantParams,
23-
PlainDateParams,
24-
PlainDateTimeParams,
25-
PlainMonthDayParams,
26-
PlainTimeParams,
27-
PlainYearMonthParams
28-
} from './internaltypes';
19+
import { DateTimeFormatParams as Params, DateTimeFormatReturn as Return } from './internaltypes';
2920

3021
const DATE = Symbol('date');
3122
const YM = Symbol('ym');
@@ -340,7 +331,9 @@ function amend(optionsParam: Intl.DateTimeFormatOptions = {}, amended: MaybeFals
340331
return options as globalThis.Intl.DateTimeFormatOptions;
341332
}
342333

343-
function timeAmend(optionsParam: Intl.DateTimeFormatOptions) {
334+
type OptionsType<T extends TypesWithToLocaleString> = NonNullable<Parameters<T['toLocaleString']>[1]>;
335+
336+
function timeAmend(optionsParam: OptionsType<Temporal.PlainTime>) {
344337
let options = amend(optionsParam, {
345338
year: false,
346339
month: false,
@@ -359,7 +352,7 @@ function timeAmend(optionsParam: Intl.DateTimeFormatOptions) {
359352
return options;
360353
}
361354

362-
function yearMonthAmend(optionsParam: PlainYearMonthParams['toLocaleString'][1]) {
355+
function yearMonthAmend(optionsParam: OptionsType<Temporal.PlainYearMonth>) {
363356
let options = amend(optionsParam, {
364357
day: false,
365358
hour: false,
@@ -377,7 +370,7 @@ function yearMonthAmend(optionsParam: PlainYearMonthParams['toLocaleString'][1])
377370
return options;
378371
}
379372

380-
function monthDayAmend(optionsParam: PlainMonthDayParams['toLocaleString'][1]) {
373+
function monthDayAmend(optionsParam: OptionsType<Temporal.PlainMonthDay>) {
381374
let options = amend(optionsParam, {
382375
year: false,
383376
hour: false,
@@ -395,7 +388,7 @@ function monthDayAmend(optionsParam: PlainMonthDayParams['toLocaleString'][1]) {
395388
return options;
396389
}
397390

398-
function dateAmend(optionsParam: PlainDateParams['toLocaleString'][1]) {
391+
function dateAmend(optionsParam: OptionsType<Temporal.PlainDate>) {
399392
let options = amend(optionsParam, {
400393
hour: false,
401394
minute: false,
@@ -414,7 +407,7 @@ function dateAmend(optionsParam: PlainDateParams['toLocaleString'][1]) {
414407
return options;
415408
}
416409

417-
function datetimeAmend(optionsParam: PlainDateTimeParams['toLocaleString'][1]) {
410+
function datetimeAmend(optionsParam: OptionsType<Temporal.PlainDateTime>) {
418411
let options = amend(optionsParam, { timeZoneName: false });
419412
if (!hasTimeOptions(options) && !hasDateOptions(options)) {
420413
options = ObjectAssign({}, options, {
@@ -429,7 +422,7 @@ function datetimeAmend(optionsParam: PlainDateTimeParams['toLocaleString'][1]) {
429422
return options;
430423
}
431424

432-
function zonedDateTimeAmend(optionsParam: PlainTimeParams['toLocaleString'][1]) {
425+
function zonedDateTimeAmend(optionsParam: OptionsType<Temporal.PlainTime>) {
433426
let options = optionsParam;
434427
if (!hasTimeOptions(options) && !hasDateOptions(options)) {
435428
options = ObjectAssign({}, options, {
@@ -445,7 +438,7 @@ function zonedDateTimeAmend(optionsParam: PlainTimeParams['toLocaleString'][1])
445438
return options;
446439
}
447440

448-
function instantAmend(optionsParam: InstantParams['toLocaleString'][1]) {
441+
function instantAmend(optionsParam: OptionsType<Temporal.Instant>) {
449442
let options = optionsParam;
450443
if (!hasTimeOptions(options) && !hasDateOptions(options)) {
451444
options = ObjectAssign({}, options, {
@@ -460,11 +453,11 @@ function instantAmend(optionsParam: InstantParams['toLocaleString'][1]) {
460453
return options;
461454
}
462455

463-
function hasDateOptions(options: Parameters<TypesWithToLocaleString['toLocaleString']>[1]) {
456+
function hasDateOptions(options: OptionsType<TypesWithToLocaleString>) {
464457
return 'year' in options || 'month' in options || 'day' in options || 'weekday' in options || 'dateStyle' in options;
465458
}
466459

467-
function hasTimeOptions(options: Parameters<TypesWithToLocaleString['toLocaleString']>[1]) {
460+
function hasTimeOptions(options: OptionsType<TypesWithToLocaleString>) {
468461
return (
469462
'hour' in options || 'minute' in options || 'second' in options || 'timeStyle' in options || 'dayPeriod' in options
470463
);
@@ -509,7 +502,8 @@ type TypesWithToLocaleString =
509502
| Temporal.PlainTime
510503
| Temporal.PlainYearMonth
511504
| Temporal.PlainMonthDay
512-
| Temporal.ZonedDateTime;
505+
| Temporal.ZonedDateTime
506+
| Temporal.Instant;
513507

514508
function extractOverrides(temporalObj: Params['format'][0], main: DateTimeFormatImpl) {
515509
const DateTime = GetIntrinsic('%Temporal.PlainDateTime%');

lib/intrinsicclass.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ interface StandaloneIntrinsics {
3636
'Temporal.Calendar.from': typeof Temporal.Calendar.from;
3737
}
3838
type RegisteredStandaloneIntrinsics = { [key in keyof StandaloneIntrinsics as `%${key}%`]: StandaloneIntrinsics[key] };
39-
const INTRINSICS: Partial<TemporalIntrinsicRegisteredKeys> &
40-
Partial<TemporalIntrinsicPrototypeRegisteredKeys> &
41-
Partial<RegisteredStandaloneIntrinsics> = {};
39+
const INTRINSICS = {} as TemporalIntrinsicRegisteredKeys &
40+
TemporalIntrinsicPrototypeRegisteredKeys &
41+
RegisteredStandaloneIntrinsics;
4242

4343
type customFormatFunction<T> = (
4444
this: T,
@@ -96,13 +96,13 @@ export function MakeIntrinsicClass(
9696
});
9797
}
9898
for (const prop of Object.getOwnPropertyNames(Class)) {
99-
const desc = Object.getOwnPropertyDescriptor(Class, prop);
99+
const desc = Object.getOwnPropertyDescriptor(Class, prop) as PropertyDescriptor;
100100
if (!desc.configurable || !desc.enumerable) continue;
101101
desc.enumerable = false;
102102
Object.defineProperty(Class, prop, desc);
103103
}
104104
for (const prop of Object.getOwnPropertyNames(Class.prototype)) {
105-
const desc = Object.getOwnPropertyDescriptor(Class.prototype, prop);
105+
const desc = Object.getOwnPropertyDescriptor(Class.prototype, prop) as PropertyDescriptor;
106106
if (!desc.configurable || !desc.enumerable) continue;
107107
desc.enumerable = false;
108108
Object.defineProperty(Class.prototype, prop, desc);

lib/plaintime.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ type TemporalTimeToStringOptions = {
4343
function TemporalTimeToString(
4444
time: Temporal.PlainTime,
4545
precision: ReturnType<typeof ES.ToSecondsStringPrecision>['precision'],
46-
options: TemporalTimeToStringOptions = undefined
46+
options: TemporalTimeToStringOptions | undefined = undefined
4747
) {
4848
let hour = GetSlot(time, ISO_HOUR);
4949
let minute = GetSlot(time, ISO_MINUTE);

lib/timezone.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export class TimeZone implements Temporal.TimeZone {
125125
return null;
126126
}
127127

128-
let epochNanoseconds = GetSlot(startingPoint, EPOCHNANOSECONDS);
128+
let epochNanoseconds: JSBI | null = GetSlot(startingPoint, EPOCHNANOSECONDS);
129129
const Instant = GetIntrinsic('%Temporal.Instant%');
130130
epochNanoseconds = ES.GetIANATimeZoneNextTransition(epochNanoseconds, id);
131131
return epochNanoseconds === null ? null : new Instant(epochNanoseconds);
@@ -140,7 +140,7 @@ export class TimeZone implements Temporal.TimeZone {
140140
return null;
141141
}
142142

143-
let epochNanoseconds = GetSlot(startingPoint, EPOCHNANOSECONDS);
143+
let epochNanoseconds: JSBI | null = GetSlot(startingPoint, EPOCHNANOSECONDS);
144144
const Instant = GetIntrinsic('%Temporal.Instant%');
145145
epochNanoseconds = ES.GetIANATimeZonePreviousTransition(epochNanoseconds, id);
146146
return epochNanoseconds === null ? null : new Instant(epochNanoseconds);

lib/zoneddatetime.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,9 @@ export class ZonedDateTime implements Temporal.ZonedDateTime {
225225
entries.push([fieldName, undefined]);
226226
}
227227
});
228-
let fields = ES.PrepareTemporalFields(this, entries as any);
228+
let fields = ES.PrepareTemporalFields(this, entries);
229229
fields = ES.CalendarMergeFields(calendar, fields, props);
230-
fields = ES.PrepareTemporalFields(fields, entries as any);
230+
fields = ES.PrepareTemporalFields(fields, entries);
231231
const { year, month, day, hour, minute, second, millisecond, microsecond, nanosecond } =
232232
ES.InterpretTemporalDateTimeFields(calendar, fields, options);
233233
const offsetNs = ES.ParseTimeZoneOffsetString(fields.offset);

tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
"skipDefaultLibCheck": true,
2222
"strictBindCallApply": true,
2323
"strictFunctionTypes": true,
24-
// "strictNullChecks": true,
25-
// "strictPropertyInitialization": true,
24+
"strictNullChecks": true,
25+
"strictPropertyInitialization": true,
2626
"stripInternal": true,
2727
"target": "es2020",
2828
"outDir": "tsc-out/",

0 commit comments

Comments
 (0)