fix: enable typescript strictNullChecks

This commit is contained in:
Luma 2021-08-23 23:46:46 +09:00 committed by Christian Kaisermann
parent 2537314af5
commit bf4189a862
16 changed files with 73 additions and 42 deletions

View File

@ -23,7 +23,7 @@ const FORMAT_METHOD_NAMES = new Set(['format', '_', 't']);
function isFormatCall(node: Node, imports: Set<string>) {
if (node.type !== 'CallExpression') return false;
let identifier: Identifier;
let identifier: Identifier | undefined;
if (node.callee.type === 'Identifier') {
identifier = node.callee;
@ -125,7 +125,9 @@ export function collectMessageDefinitions(ast: Ast) {
definitionDict.properties.map((propNode) => {
if (propNode.type !== 'Property') {
throw new Error(
`Found invalid '${propNode.type}' at L${propNode.loc.start.line}:${propNode.loc.start.column}`,
`Found invalid '${propNode.type}' at L${propNode.loc!.start.line}:${
propNode.loc!.start.column
}`,
);
}
@ -143,7 +145,7 @@ export function collectMessages(markup: string): Message[] {
...definitions.map((definition) => getObjFromExpression(definition)),
...calls.map((call) => {
const [pathNode, options] = call.arguments;
let messageObj;
let messageObj: Partial<Message>;
if (pathNode.type === 'ObjectExpression') {
// _({ ...opts })
@ -166,7 +168,7 @@ export function collectMessages(markup: string): Message[] {
return messageObj;
}),
].filter(Boolean);
].filter((Boolean as unknown) as (x: Message | null) => x is Message);
}
export function extractMessages(

View File

@ -2,8 +2,10 @@ import type { ObjectExpression, Property, Identifier } from 'estree';
import type { Message } from '../types';
export function getObjFromExpression(exprNode: ObjectExpression) {
return exprNode.properties.reduce<Message>((acc, prop: Property) => {
export function getObjFromExpression(
exprNode: ObjectExpression,
): Partial<Message> {
return exprNode.properties.reduce<Partial<Message>>((acc, prop: Property) => {
// we only want primitives
if (
prop.value.type === 'Literal' &&

View File

@ -1,5 +1,5 @@
export interface Message {
id?: string;
default?: string;
id: string;
default: string;
[key: string]: any;
}

View File

@ -1,4 +1,4 @@
import type { ConfigureOptions } from './types';
import type { ConfigureOptions, ConfigureOptionsInit } from './types';
import { $locale } from './stores/locale';
interface Formats {
@ -47,13 +47,13 @@ export const defaultOptions: ConfigureOptions = {
ignoreTag: true,
};
const options: ConfigureOptions = defaultOptions;
const options: ConfigureOptions = defaultOptions as any;
export function getOptions() {
return options;
}
export function init(opts: ConfigureOptions) {
export function init(opts: ConfigureOptionsInit) {
const { formats, ...rest } = opts;
const initialLocale = opts.initialLocale || opts.fallbackLocale;

View File

@ -1,6 +1,9 @@
import IntlMessageFormat from 'intl-messageformat';
import type { MemoizedIntlFormatter } from '../types';
import type {
MemoizedIntlFormatter,
MemoizedIntlFormatterOptional,
} from '../types';
import { getCurrentLocale } from '../stores/locale';
import { getOptions } from '../configs';
import { monadicMemoize } from './memoize';
@ -15,6 +18,16 @@ type MemoizedDateTimeFormatterFactory = MemoizedIntlFormatter<
Intl.DateTimeFormatOptions
>;
type MemoizedNumberFormatterFactoryOptional = MemoizedIntlFormatterOptional<
Intl.NumberFormat,
Intl.NumberFormatOptions
>;
type MemoizedDateTimeFormatterFactoryOptional = MemoizedIntlFormatterOptional<
Intl.DateTimeFormat,
Intl.DateTimeFormatOptions
>;
const getIntlFormatterOptions = (
type: 'time' | 'number' | 'date',
name: string,
@ -76,17 +89,17 @@ const createTimeFormatter: MemoizedDateTimeFormatterFactory = monadicMemoize(
},
);
export const getNumberFormatter: MemoizedNumberFormatterFactory = ({
export const getNumberFormatter: MemoizedNumberFormatterFactoryOptional = ({
locale = getCurrentLocale(),
...args
} = {}) => createNumberFormatter({ locale, ...args });
export const getDateFormatter: MemoizedDateTimeFormatterFactory = ({
export const getDateFormatter: MemoizedDateTimeFormatterFactoryOptional = ({
locale = getCurrentLocale(),
...args
} = {}) => createDateFormatter({ locale, ...args });
export const getTimeFormatter: MemoizedDateTimeFormatterFactory = ({
export const getTimeFormatter: MemoizedDateTimeFormatterFactoryOptional = ({
locale = getCurrentLocale(),
...args
} = {}) => createTimeFormatter({ locale, ...args });

View File

@ -62,7 +62,7 @@ function loadLocaleQueue(locale: string, localeQueue: MessagesLoader[]) {
const activeFlushes: { [key: string]: Promise<void> } = {};
export function flush(locale: string): Promise<void> {
export async function flush(locale: string): Promise<void> {
if (!hasLocaleQueue(locale)) {
if (locale in activeFlushes) {
return activeFlushes[locale];

View File

@ -15,7 +15,7 @@ const addToCache = (path: string, locale: string, message: string) => {
return message;
};
export const lookup = (path: string, refLocale: string) => {
export const lookup = (path: string, refLocale: string | null | undefined) => {
if (refLocale == null) return undefined;
if (refLocale in lookupCache && path in lookupCache[refLocale]) {

View File

@ -31,7 +31,7 @@ export function defineMessages(i: Record<string, MessageObject>) {
}
export function waitLocale(locale?: string) {
return flush(locale || getCurrentLocale() || getOptions().initialLocale);
return flush(locale || getCurrentLocale() || getOptions().initialLocale!);
}
export {

View File

@ -34,7 +34,9 @@ export function getMessageFromDictionary(locale: string, id: string) {
return match;
}
export function getClosestAvailableLocale(refLocale: string): string | null {
export function getClosestAvailableLocale(
refLocale: string,
): string | null | undefined {
if (refLocale == null) return undefined;
const relatedLocales = getPossibleLocales(refLocale);

View File

@ -23,7 +23,7 @@ import { getCurrentLocale, getPossibleLocales, $locale } from './locale';
const formatMessage: MessageFormatter = (id, options = {}) => {
if (typeof id === 'object') {
options = id as MessageObject;
id = options.id;
id = options.id!;
}
const {
@ -90,11 +90,8 @@ const formatNumber: NumberFormatter = (n, options) => {
return getNumberFormatter(options).format(n);
};
const getJSON: JSONGetter = <T = any>(
id: string,
locale = getCurrentLocale(),
) => {
return lookup(id, locale) as T;
const getJSON: JSONGetter = (id: string, locale = getCurrentLocale()): any => {
return lookup(id, locale);
};
export const $format = derived([$locale, $dictionary], () => formatMessage);

View File

@ -6,7 +6,7 @@ import { getClosestAvailableLocale } from './dictionary';
import { $isLoading } from './loading';
let current: string;
const $locale = writable(null);
const $locale = writable<string | null | undefined>(null);
function getSubLocales(refLocale: string) {
return refLocale
@ -77,7 +77,8 @@ $locale.set = (newLocale: string): void | Promise<void> => {
};
// istanbul ignore next
$locale.update = (fn: (locale: string) => void | Promise<void>) =>
localeSet(fn(current));
$locale.update = (
fn: (value: string | null | undefined) => string | null | undefined,
) => localeSet(fn(current));
export { $locale };

View File

@ -1,7 +1,11 @@
import type { FormatXMLElementFn, Formats } from 'intl-messageformat';
export interface LocaleDictionary {
[key: string]: LocaleDictionary | string | Array<string | LocaleDictionary>;
[key: string]:
| LocaleDictionary
| string
| Array<string | LocaleDictionary>
| null;
}
export type LocalesDictionary = {
@ -49,7 +53,7 @@ export type NumberFormatter = (
options?: IntlFormatterOptions<Intl.NumberFormatOptions>,
) => string;
export type JSONGetter = <T>(id: string, locale?: string) => T;
export type JSONGetter = (id: string, locale?: string) => any;
type IntlFormatterOptions<T> = T & {
format?: string;
@ -57,6 +61,10 @@ type IntlFormatterOptions<T> = T & {
};
export interface MemoizedIntlFormatter<T, U> {
(options: IntlFormatterOptions<U>): T;
}
export interface MemoizedIntlFormatterOptional<T, U> {
(options?: IntlFormatterOptions<U>): T;
}
@ -65,10 +73,14 @@ export interface MessagesLoader {
}
export interface ConfigureOptions {
fallbackLocale: string;
formats?: Partial<Formats>;
initialLocale?: string;
loadingDelay?: number;
warnOnMissingMessages?: boolean;
ignoreTag?: boolean;
fallbackLocale: string | null | undefined;
formats: Formats;
initialLocale: string | null;
loadingDelay: number;
warnOnMissingMessages: boolean;
ignoreTag: boolean;
}
export type ConfigureOptionsInit = Pick<ConfigureOptions, 'fallbackLocale'> &
Partial<Record<'formats', Partial<ConfigureOptions['formats']>>> &
Partial<Omit<ConfigureOptions, 'fallbackLocale' | 'formats'>>;

View File

@ -23,8 +23,8 @@ test('checks if exist queues of locale and its fallbacks', () => {
expect(hasLocaleQueue('en-US')).toBe(true);
});
test("does nothing if there's no queue for a locale", () => {
expect(flush('foo')).toBeUndefined();
test("does nothing if there's no queue for a locale", async () => {
expect(await flush('foo')).toBeUndefined();
});
test('flushes the queue of a locale and its fallbacks and merge the result with the dictionary', async () => {

View File

@ -8,7 +8,7 @@ import {
describe('getting client locale', () => {
beforeEach(() => {
delete window.location;
delete (window as any).location;
window.location = {
pathname: '/',
hostname: 'example.com',

View File

@ -1,10 +1,12 @@
{
"compilerOptions": {
"allowJs": true,
"strictNullChecks": true,
"noImplicitAny": true,
"sourceMap": false,
"module": "esnext",
"moduleResolution": "node",
"skipLibCheck": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"target": "es2017",

View File

@ -1263,9 +1263,9 @@
integrity sha512-lg55ArB+ZiHHbBBttLpzD07akz0QPrZgUODNakeC09i62dnrywr9mFErHuaPlB6I7z+sEbK+IYmplahvplCj2g==
"@types/node@^14.14.35":
version "14.14.35"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.35.tgz#42c953a4e2b18ab931f72477e7012172f4ffa313"
integrity sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag==
version "14.17.11"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.11.tgz#82d266d657aec5ff01ca59f2ffaff1bb43f7bf0f"
integrity sha512-n2OQ+0Bz6WEsUjrvcHD1xZ8K+Kgo4cn9/w94s1bJS690QMUWfJPW/m7CCb7gPkA1fcYwL2UpjXP/rq/Eo41m6w==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"