Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
Typescript 4.9 (#2409)
Browse files Browse the repository at this point in the history
- Update types to account for lib.d.ts changes regarding Navigator and
  Window.
- Propagate generic constraints
  • Loading branch information
BPScott authored Feb 7, 2023
1 parent 99a9903 commit 0bff6fa
Show file tree
Hide file tree
Showing 31 changed files with 106 additions and 72 deletions.
14 changes: 14 additions & 0 deletions .changeset/lovely-impalas-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
'graphql-fixtures': minor
'graphql-mini-transforms': minor
'@shopify/jest-dom-mocks': minor
'@shopify/react-async': minor
'@shopify/react-form-state': minor
'@shopify/react-graphql': minor
'@shopify/react-idle': minor
'@shopify/react-import-remote': minor
'@shopify/react-server': minor
'@shopify/react-testing': minor
---

Update types to account changes in TypeScript 4.8 and 4.9. [Propogate contstraints on generic types](https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/#unconstrained-generics-no-longer-assignable-to) and update type usage relating to `Window` and `Navigator`. Technically this makes some types stricter, as attempting to pass `null|undefined` into certain functions is now disallowed by TypeScript, but these were never expected runtime values in the first place.
5 changes: 5 additions & 0 deletions .changeset/purple-pumpkins-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/react-graphql': minor
---

`extends {}` has been added to the `Data` / `Variables` / `DeepPartial` generic types on the `useQuery` and `useGraphQLDocument` hooks, the `createAsyncQuery`,`createAsyncQueryComponent` functions and the `Query` component. If you use typescript's `strictNullChecks` option and define functions that contain generics that are then passed into any of these functions you may need add an `extends {}` to your code as well, per [the typescript 4.8 changelog](https://devblogs.microsoft.com/typescript/announcing-typescript-4-8/#unconstrained-generics-no-longer-assignable-to). For example, replace `<Data>` with `<Data extends {}>`.
6 changes: 6 additions & 0 deletions .changeset/rotten-swans-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@shopify/react-idle': patch
'@shopify/react-import-remote': patch
---

Remove dependency on `@shopify/useful-types`
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"react18": "npm:react@^18.1.0",
"rimraf": "^2.6.2",
"tsd": "^0.19.1",
"typescript": "~4.7.4",
"typescript": "~4.9.3",
"yalc": "^1.0.0-pre.50"
}
}
19 changes: 16 additions & 3 deletions packages/graphql-fixtures/src/fill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,25 @@ export type DeepThunk<T, Data, Variables, DeepPartial> =
| null
| undefined;

// The `undefined extends Variables ? {} : Variables` dance is needed to coerce
// variables that are undefined to an empty object, so that it matches the shape
// of `GraphQLOperation`, because that has a default value of `{}` on the
// variables generic type.
export type GraphQLFillerData<Operation extends GraphQLOperation> =
Operation extends GraphQLOperation<
infer Data,
infer Variables,
infer PartialData
>
? Thunk<
DeepThunk<PartialData, Data, Variables, PartialData>,
DeepThunk<
PartialData,
Data,
undefined extends Variables ? {} : Variables,
PartialData
>,
Data,
Variables,
undefined extends Variables ? {} : Variables,
PartialData
>
: never;
Expand Down Expand Up @@ -149,7 +158,11 @@ export function createFiller(

const context = {schema, resolvers};

return function fill<Data, Variables, PartialData>(
return function fill<
Data extends {},
Variables extends {},
PartialData extends {},
>(
_document: GraphQLOperation<Data, Variables, PartialData>,
data?: GraphQLFillerData<GraphQLOperation<Data, Variables, PartialData>>,
): (request: GraphQLRequest<Data, Variables, PartialData>) => Data {
Expand Down
6 changes: 5 additions & 1 deletion packages/graphql-mini-transforms/src/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ export function extractImports(rawSource: string) {
return {imports: [...imports], source};
}

export function toSimpleDocument<Data, Variables, DeepPartial>(
export function toSimpleDocument<
Data extends {},
Variables extends {},
DeepPartial extends {},
>(
document: DocumentNode<Data, Variables, DeepPartial>,
): SimpleDocument<Data, Variables, DeepPartial> {
return {
Expand Down
3 changes: 2 additions & 1 deletion packages/jest-dom-mocks/src/connection.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {set} from './utilities';

export interface NavigatorWithConnection extends Navigator {
connection: Navigator['connection'] & {
connection: EventTarget & {
type: string;
downlink: number;
effectiveType: string;
onchange: null | Function;
Expand Down
6 changes: 4 additions & 2 deletions packages/jest-dom-mocks/src/tests/connection.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Connection} from '../connection';
import {Connection, NavigatorWithConnection} from '../connection';

describe('Connection', () => {
describe('mock', () => {
Expand Down Expand Up @@ -29,7 +29,9 @@ describe('Connection', () => {

connection.mock(mockValues);

expect(navigator.connection).toMatchObject(mockValues);
expect((navigator as NavigatorWithConnection).connection).toMatchObject(
mockValues,
);
});
});

Expand Down
2 changes: 1 addition & 1 deletion packages/react-async/src/Prefetcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface State {
}

interface NavigatorWithConnection extends Navigator {
connection: Navigator['connection'] & {saveData: boolean};
connection: {saveData: boolean};
}

export const INTENTION_DELAY_MS = 150;
Expand Down
11 changes: 7 additions & 4 deletions packages/react-form-state/src/FormState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,10 @@ export default class FormState<
static List = List;
static Nested = Nested;

static getDerivedStateFromProps<T>(newProps: Props<T>, oldState: State<T>) {
static getDerivedStateFromProps<T extends object>(
newProps: Props<T>,
oldState: State<T>,
) {
const {
initialValues,
onInitialValuesChange,
Expand Down Expand Up @@ -409,7 +412,7 @@ export default class FormState<
}
}

function fieldsWithErrors<Fields>(
function fieldsWithErrors<Fields extends object>(
fields: Fields,
errors: RemoteError[],
): Fields {
Expand All @@ -436,7 +439,7 @@ function fieldsWithErrors<Fields>(
});
}

function reconcileFormState<Fields>(
function reconcileFormState<Fields extends object>(
values: Fields,
oldState: State<Fields>,
externalErrors: RemoteError[] = [],
Expand Down Expand Up @@ -467,7 +470,7 @@ function reconcileFormState<Fields>(
};
}

function createFormState<Fields>(
function createFormState<Fields extends object>(
values: Fields,
externalErrors: RemoteError[] = [],
): State<Fields> {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-form-state/src/components/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface Props<Fields> {
getChildKey?(item: Fields): string;
}

export default class List<Fields> extends React.PureComponent<
export default class List<Fields extends object> extends React.PureComponent<
Props<Fields>,
never
> {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-form-state/src/components/Nested.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ interface Props<Fields> {
children(fields: FieldDescriptors<Fields>): React.ReactNode;
}

export default class Nested<Fields> extends React.PureComponent<
export default class Nested<Fields extends object> extends React.PureComponent<
Props<Fields>,
never
> {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-form-state/src/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {FieldDescriptor} from './types';

export {isEqual};

export function mapObject<Input, Output>(
export function mapObject<Input extends object, Output>(
input: Input,
mapper: (value: any, key: string & keyof Input) => any,
) {
Expand Down
2 changes: 1 addition & 1 deletion packages/react-graphql/src/Prefetch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type Props<T> = Pick<
'query' | 'variables' | 'onError' | 'onCompleted' | 'pollInterval'
> & {ignoreCache?: boolean};

export function Prefetch<T>({ignoreCache, ...props}: Props<T>) {
export function Prefetch<T extends {}>({ignoreCache, ...props}: Props<T>) {
const fetchPolicy = ignoreCache ? 'network-only' : undefined;

return (
Expand Down
9 changes: 4 additions & 5 deletions packages/react-graphql/src/Query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ interface QueryComponentOptions<Data, Variables> extends QueryHookOptions {
query: DocumentNode<Data, Variables>;
}

export function Query<Data = any, Variables = OperationVariables>({
children,
query,
...options
}: QueryComponentOptions<Data, Variables>) {
export function Query<
Data extends {} = any,
Variables extends OperationVariables = OperationVariables,
>({children, query, ...options}: QueryComponentOptions<Data, Variables>) {
const opts = [options] as IfAllNullableKeys<
Variables,
[QueryHookOptions<Data, NoInfer<Variables>>?],
Expand Down
6 changes: 5 additions & 1 deletion packages/react-graphql/src/async/component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import {AsyncQueryComponentType, QueryProps, VariableOptions} from '../types';

import {Options, createAsyncQuery} from './query';

export function createAsyncQueryComponent<Data, Variables, DeepPartial>(
export function createAsyncQueryComponent<
Data extends {},
Variables extends {},
DeepPartial extends {},
>(
options: Options<Data, Variables, DeepPartial>,
): AsyncQueryComponentType<Data, Variables, DeepPartial> {
const asyncQuery = createAsyncQuery(options);
Expand Down
6 changes: 5 additions & 1 deletion packages/react-graphql/src/async/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import {AsyncDocumentNode, QueryProps, VariableOptions} from '../types';
export interface Options<Data, Variables, DeepPartial>
extends ResolverOptions<DocumentNode<Data, Variables, DeepPartial>> {}

export function createAsyncQuery<Data, Variables, DeepPartial>({
export function createAsyncQuery<
Data extends {},
Variables extends {},
DeepPartial extends {},
>({
id,
load,
}: Options<Data, Variables, DeepPartial>): AsyncDocumentNode<
Expand Down
6 changes: 3 additions & 3 deletions packages/react-graphql/src/hooks/graphql-document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import {useAsyncAsset} from '@shopify/react-async';
import {AsyncDocumentNode} from '../types';

export default function useGraphQLDocument<
Data = any,
Variables = OperationVariables,
DeepPartial = {},
Data extends {} = any,
Variables extends OperationVariables = OperationVariables,
DeepPartial extends {} = {},
>(
documentOrAsyncDocument:
| DocumentNode<Data, Variables>
Expand Down
6 changes: 3 additions & 3 deletions packages/react-graphql/src/hooks/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ const {
} = Object;

export default function useQuery<
Data = any,
Variables = OperationVariables,
DeepPartial = {},
Data extends {} = any,
Variables extends OperationVariables = OperationVariables,
DeepPartial extends {} = {},
>(
queryOrAsyncQuery:
| DocumentNode<Data, Variables, DeepPartial>
Expand Down
3 changes: 1 addition & 2 deletions packages/react-idle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
"node": "^14.17.0 || >=16.0.0"
},
"dependencies": {
"@shopify/async": "^4.0.1",
"@shopify/useful-types": "^5.1.1"
"@shopify/async": "^4.0.1"
},
"peerDependencies": {
"react": ">=16.8.0 <19.0.0"
Expand Down
19 changes: 5 additions & 14 deletions packages/react-idle/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import {useEffect, useRef} from 'react';
import {ExtendedWindow} from '@shopify/useful-types';

import {
RequestIdleCallbackHandle,
WindowWithRequestIdleCallback,
UnsupportedBehavior,
} from './types';
import {RequestIdleCallbackHandle, UnsupportedBehavior} from './types';

export function useIdleCallback(
callback: () => void,
Expand All @@ -15,11 +10,9 @@ export function useIdleCallback(

useEffect(() => {
if ('requestIdleCallback' in window) {
handle.current = (
window as ExtendedWindow<WindowWithRequestIdleCallback>
).requestIdleCallback(() => callback());
handle.current = window.requestIdleCallback(() => callback());
} else if (unsupportedBehavior === UnsupportedBehavior.AnimationFrame) {
handle.current = window.requestAnimationFrame(() => {
handle.current = (window as Window).requestAnimationFrame(() => {
callback();
});
} else {
Expand All @@ -35,11 +28,9 @@ export function useIdleCallback(
}

if ('cancelIdleCallback' in window) {
(
window as ExtendedWindow<WindowWithRequestIdleCallback>
).cancelIdleCallback(currentHandle);
window.cancelIdleCallback(currentHandle);
} else if (unsupportedBehavior === UnsupportedBehavior.AnimationFrame) {
window.cancelAnimationFrame(currentHandle);
(window as Window).cancelAnimationFrame(currentHandle);
}
};
}, [callback, unsupportedBehavior]);
Expand Down
1 change: 0 additions & 1 deletion packages/react-idle/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export type {
RequestIdleCallbackOptions,
RequestIdleCallbackDeadline,
RequestIdleCallbackHandle,
WindowWithRequestIdleCallback,
} from '@shopify/async';

export enum UnsupportedBehavior {
Expand Down
3 changes: 1 addition & 2 deletions packages/react-idle/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"references": [
{"path": "../async"},
{"path": "../jest-dom-mocks"},
{"path": "../react-testing"},
{"path": "../useful-types"}
{"path": "../react-testing"}
]
}
3 changes: 1 addition & 2 deletions packages/react-import-remote/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@
"@shopify/async": "^4.0.1",
"@shopify/react-hooks": "^3.0.2",
"@shopify/react-html": "^13.0.0",
"@shopify/react-intersection-observer": "^4.0.2",
"@shopify/useful-types": "^5.1.1"
"@shopify/react-intersection-observer": "^4.0.2"
},
"peerDependencies": {
"react": ">=16.8.0 <19.0.0"
Expand Down
11 changes: 2 additions & 9 deletions packages/react-import-remote/src/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import React from 'react';
import {ExtendedWindow} from '@shopify/useful-types';
import {useIntersection} from '@shopify/react-intersection-observer';
import {
DeferTiming,
WindowWithRequestIdleCallback,
RequestIdleCallbackHandle,
} from '@shopify/async';
import {DeferTiming, RequestIdleCallbackHandle} from '@shopify/async';
import {useMountedRef} from '@shopify/react-hooks';

import load from './load';
Expand Down Expand Up @@ -98,9 +93,7 @@ export function useImportRemote<Imported = unknown>(
React.useEffect(() => {
if (defer === DeferTiming.Idle) {
if ('requestIdleCallback' in window) {
idleCallbackHandle.current = (
window as ExtendedWindow<WindowWithRequestIdleCallback>
).requestIdleCallback(loadRemote);
idleCallbackHandle.current = window.requestIdleCallback(loadRemote);
} else {
loadRemote();
}
Expand Down
4 changes: 2 additions & 2 deletions packages/react-import-remote/src/load.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ExtendedWindow} from '@shopify/useful-types';

const cache = new Map<string, Promise<any>>();

type ExtendedWindow<T> = Window & typeof globalThis & T;

export default function load<
Imported = any,
CustomWindow extends Window = Window,
Expand Down
3 changes: 1 addition & 2 deletions packages/react-import-remote/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
{"path": "../async"},
{"path": "../react-hooks"},
{"path": "../react-html"},
{"path": "../react-intersection-observer"},
{"path": "../useful-types"}
{"path": "../react-intersection-observer"}
]
}
2 changes: 1 addition & 1 deletion packages/react-server/src/tests/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class TestRack {
}

async mount(
mountFunction: ({port: number, ip: string}) => Server,
mountFunction: ({port, ip}: {port: number; ip: string}) => Server,
options: RequestInit = {},
) {
const port = await getPort();
Expand Down
Loading

0 comments on commit 0bff6fa

Please sign in to comment.