From 76a868d47355b016a1c9216f94fef79e6187eab4 Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Sun, 4 Aug 2024 16:42:11 -0400 Subject: [PATCH 1/7] refactor PixiElement and PixiReactNode types --- src/typedefs/PixiElements.ts | 6 +----- src/typedefs/PixiReactNode.ts | 24 +++++++----------------- src/typedefs/UtilityTypes.ts | 7 +++++++ 3 files changed, 15 insertions(+), 22 deletions(-) create mode 100644 src/typedefs/UtilityTypes.ts diff --git a/src/typedefs/PixiElements.ts b/src/typedefs/PixiElements.ts index eb271c51..9fb9d586 100644 --- a/src/typedefs/PixiElements.ts +++ b/src/typedefs/PixiElements.ts @@ -4,9 +4,5 @@ import type { PixiComponents } from './PixiComponents'; import type { PixiReactElementProps } from './PixiReactNode'; export type PixiElements = { - [K in PixiComponents as K extends keyof typeof NameOverrides ? typeof NameOverrides[K] : Uncapitalize]: { - [K2 in keyof PixiReactElementProps as K2]?: PixiReactElementProps[K2] extends (...args: any) => any - ? never - : PixiReactElementProps[K2]; - }; + [K in PixiComponents as K extends keyof typeof NameOverrides ? typeof NameOverrides[K] : Uncapitalize]: PixiReactElementProps; }; diff --git a/src/typedefs/PixiReactNode.ts b/src/typedefs/PixiReactNode.ts index 23077b6a..13b44525 100644 --- a/src/typedefs/PixiReactNode.ts +++ b/src/typedefs/PixiReactNode.ts @@ -1,3 +1,7 @@ +import { type PixiToReactEventPropNames } from '../constants/EventPropNames'; +import { type ConstructorOptions } from './ConstructorOptions'; +import { type ExcludeFunctionProps, type OmitKeys } from './UtilityTypes'; + import type { Container, Graphics, @@ -6,8 +10,6 @@ import type { Key, Ref, } from 'react'; -import type { PixiToReactEventPropNames } from '../constants/EventPropNames'; -import type { ConstructorOptions } from './ConstructorOptions'; import type { DrawCallback } from './DrawCallback'; import type { EventHandlers } from './EventHandlers'; import type { InstanceState } from './InstanceState'; @@ -15,7 +17,7 @@ import type { PixiReactChildNode } from './PixiReactChildNode'; export interface BaseNodeProps any = typeof Container> { - children: T extends Container + children?: T extends Container ? PixiReactChildNode : never; draw?: T extends Graphics @@ -42,17 +44,5 @@ export type PixiReactNode any = typeof Container export type PixiReactElementProps any = typeof Container> = BaseNodeProps> - & EventHandlers - & { - [ - K in keyof ConstructorOptions as ( - K extends keyof typeof PixiToReactEventPropNames - ? never - : K extends keyof NodeProps> - ? ConstructorOptions[K] extends NodeProps>[K] - ? never - : K - : K - ) - ]: ConstructorOptions[K]; - }; + & OmitKeys>, NodeProps & typeof PixiToReactEventPropNames> + & EventHandlers; diff --git a/src/typedefs/UtilityTypes.ts b/src/typedefs/UtilityTypes.ts new file mode 100644 index 00000000..5bb107f1 --- /dev/null +++ b/src/typedefs/UtilityTypes.ts @@ -0,0 +1,7 @@ +export type ExcludeFunctionProps = { + [K in keyof T as T[K] extends (...args: any[]) => any ? never : K]: T[K]; +}; + +export type OmitKeys = { + [K in keyof T1 as K extends keyof T2 ? never : K]: T1[K]; +}; From a3ab33a79c3159ee2df134ad9e734e71a33bffcb Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Sun, 4 Aug 2024 23:18:18 -0400 Subject: [PATCH 2/7] ensure DrawCallback is only available on Graphics --- src/typedefs/PixiReactNode.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/typedefs/PixiReactNode.ts b/src/typedefs/PixiReactNode.ts index 13b44525..fae78584 100644 --- a/src/typedefs/PixiReactNode.ts +++ b/src/typedefs/PixiReactNode.ts @@ -20,13 +20,13 @@ export interface BaseNodeProps any = typeof Cont children?: T extends Container ? PixiReactChildNode : never; - draw?: T extends Graphics - ? DrawCallback - : null; key?: Key; ref?: Ref; } +export type GraphicsProps = T extends Graphics ? + { draw: DrawCallback } : unknown; + export interface NodeProps any = typeof Container> extends BaseNodeProps { __pixireact: InstanceState, @@ -44,5 +44,6 @@ export type PixiReactNode any = typeof Container export type PixiReactElementProps any = typeof Container> = BaseNodeProps> + & GraphicsProps> & OmitKeys>, NodeProps & typeof PixiToReactEventPropNames> & EventHandlers; From f58b2a8b3a14dfce0d29cc565f608b51858c5f58 Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Wed, 7 Aug 2024 15:18:47 -0400 Subject: [PATCH 3/7] fix ConstructorOverrides & setup type checking on tests (n/a type tests) --- .vscode/settings.json | 3 +++ package.json | 2 +- src/helpers/applyProps.ts | 2 +- src/typedefs/ConstructorOptions.ts | 10 +++---- src/typedefs/ConstructorOverrides.ts | 3 ++- test/unit/typedefs/PixiElements.test.tsx | 31 +++++++++++++++++++++ tsconfig.eslint.json | 1 + tsconfig.json | 3 ++- tsconfig.test.json | 34 ++++++++++++++++++++++++ vitest.workspace.ts | 2 +- 10 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 test/unit/typedefs/PixiElements.test.tsx create mode 100644 tsconfig.test.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..3662b370 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/package.json b/package.json index 0b3f23d8..8f236ba8 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "prepare": "husky install", "prerelease": "npm run test:lint && npm run build", "release": "xs bump,publish,git-push", - "test": "vitest run", + "test": "tsc --project tsconfig.test.json && vitest run", "test:lint": "xs lint", "test:watch": "vitest" }, diff --git a/src/helpers/applyProps.ts b/src/helpers/applyProps.ts index 1389e1df..57bc00fb 100644 --- a/src/helpers/applyProps.ts +++ b/src/helpers/applyProps.ts @@ -85,7 +85,7 @@ export function applyProps( let currentInstance = instance; let targetProp = currentInstance[key]; - if ((key === 'draw') && (typeof value === 'function')) + if ((key as string === 'draw') && (typeof value === 'function')) { if (instance instanceof Graphics) { diff --git a/src/typedefs/ConstructorOptions.ts b/src/typedefs/ConstructorOptions.ts index 14993e20..f2921a93 100644 --- a/src/typedefs/ConstructorOptions.ts +++ b/src/typedefs/ConstructorOptions.ts @@ -5,8 +5,8 @@ import type { ConstructorOverrides } from './ConstructorOverrides'; * @see https://github.com/pixijs/pixi-react/issues/500 */ export type ConstructorOptions any> = - Extract extends [T, infer R] - ? unknown extends R - ? ConstructorParameters[0] - : R - : never; + T extends new (...args: any[]) => infer Instance + ? Instance extends keyof ConstructorOverrides + ? ConstructorOverrides[Instance] + : ConstructorParameters[0] + : unknown; diff --git a/src/typedefs/ConstructorOverrides.ts b/src/typedefs/ConstructorOverrides.ts index 046ec053..5e17aaeb 100644 --- a/src/typedefs/ConstructorOverrides.ts +++ b/src/typedefs/ConstructorOverrides.ts @@ -22,4 +22,5 @@ export type ConstructorOverrides = | [typeof DisplacementFilter, DisplacementFilterOptions] | [typeof Filter, FilterOptions] | [typeof NoiseFilter, NoiseFilterOptions] - | [typeof Text, TextOptions]; + | [typeof Text, TextOptions] + | unknown; diff --git a/test/unit/typedefs/PixiElements.test.tsx b/test/unit/typedefs/PixiElements.test.tsx new file mode 100644 index 00000000..cb82365e --- /dev/null +++ b/test/unit/typedefs/PixiElements.test.tsx @@ -0,0 +1,31 @@ +import { AlphaFilter, Container, Graphics, Sprite, Text, Texture } from 'pixi.js'; +import { describe, expect, it } from 'vitest'; +import { extend } from '../../../src'; + +extend({ Container, Graphics, Sprite, Text, Texture, AlphaFilter }); + +describe('PixiElements', () => +{ + it('applies children and props', () => + { + const elements = ( + + { /* noop */ }} /> + + + + ); + + expect(elements.props.children).to.have.length(3); + + expect(elements.props.children[0].type).to.equal('graphics'); + expect(elements.props.children[0].props.draw).to.be.a('function'); + + expect(elements.props.children[1].type).to.equal('sprite'); + expect(elements.props.children[1].props.draw).to.be.undefined; + expect(elements.props.children[1].props.texture).to.be.instanceOf(Texture); + + expect(elements.props.children[2].type).to.equal('alphaFilter'); + expect(elements.props.children[2].props.alpha).to.equal(0.5); + }); +}); diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index f3f0a798..61f09d4c 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -5,6 +5,7 @@ "release.config.js", ], "include": [ + "./src/**/*", "./test/**/*", "./vitest.setup.ts", "./vitest.workspace.ts" diff --git a/tsconfig.json b/tsconfig.json index 0673a6f4..529b6c0e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,9 +28,10 @@ "exclude": [ "dist", "node_modules", - "types" + "types", ], "include": [ "./src/**/*", + "./test/**/*" ], } diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 00000000..f7bb37ed --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,34 @@ + +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "allowJs": true, + "allowImportingTsExtensions": true, + "allowSyntheticDefaultImports": true, + "baseUrl": "./src", + "checkJs": true, + "noEmit": true, + "emitDeclarationOnly": false, + "esModuleInterop": true, + "jsx": "react-jsx", + "lib": [ + "DOM", + "ESNext" + ], + "module": "ESNext", + "moduleResolution": "node", + "noUnusedLocals": true, + "noUnusedParameters": true, + "pretty": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "target": "ESNext" + }, + "exclude": [ + "dist", + "node_modules", + "types" + ], +} diff --git a/vitest.workspace.ts b/vitest.workspace.ts index 736729bb..090e991e 100644 --- a/vitest.workspace.ts +++ b/vitest.workspace.ts @@ -4,7 +4,7 @@ export default defineWorkspace([ { test: { environment: 'jsdom', - include: ['test/unit/**/*.test.ts'], + include: ['test/unit/**/*.test.ts?(x)'], pool: 'forks', }, }, From d531ad2f665f5b701748a9703242f5714ba71e72 Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Wed, 7 Aug 2024 20:19:15 -0400 Subject: [PATCH 4/7] ensure we include lib in lint config --- tsconfig.eslint.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 61f09d4c..e5818db1 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -5,7 +5,7 @@ "release.config.js", ], "include": [ - "./src/**/*", + "./lib/**/*", "./test/**/*", "./vitest.setup.ts", "./vitest.workspace.ts" From 96217f019a3f6f8d1a4c6c6d59d6be6d5d8e88f6 Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Wed, 7 Aug 2024 20:23:54 -0400 Subject: [PATCH 5/7] wrap long line --- src/typedefs/PixiElements.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/typedefs/PixiElements.ts b/src/typedefs/PixiElements.ts index 9fb9d586..6a6e0ef4 100644 --- a/src/typedefs/PixiElements.ts +++ b/src/typedefs/PixiElements.ts @@ -4,5 +4,6 @@ import type { PixiComponents } from './PixiComponents'; import type { PixiReactElementProps } from './PixiReactNode'; export type PixiElements = { - [K in PixiComponents as K extends keyof typeof NameOverrides ? typeof NameOverrides[K] : Uncapitalize]: PixiReactElementProps; + [K in PixiComponents as K extends keyof typeof NameOverrides ? typeof NameOverrides[K] : Uncapitalize]: + PixiReactElementProps; }; From e605f53f3a982932526e126a4a3946e856b1c88a Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Thu, 8 Aug 2024 09:11:51 -0400 Subject: [PATCH 6/7] Fix typescript project structure, adds tsconfig to the root of tests to satisfy vscode. --- test/tsconfig.json | 3 +++ tsconfig.json | 1 - tsconfig.test.json | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 test/tsconfig.json diff --git a/test/tsconfig.json b/test/tsconfig.json new file mode 100644 index 00000000..4ff0a8e2 --- /dev/null +++ b/test/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../tsconfig.test.json", +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 529b6c0e..571d2b0c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -32,6 +32,5 @@ ], "include": [ "./src/**/*", - "./test/**/*" ], } diff --git a/tsconfig.test.json b/tsconfig.test.json index f7bb37ed..442baec5 100644 --- a/tsconfig.test.json +++ b/tsconfig.test.json @@ -31,4 +31,8 @@ "node_modules", "types" ], + "include": [ + "./src/**/*", + "./test/**/*", + ] } From 26b969aa846814895d2ea8d8e82af064984f0a9a Mon Sep 17 00:00:00 2001 From: Justin Walsh Date: Thu, 8 Aug 2024 09:53:31 -0400 Subject: [PATCH 7/7] revert constructor options changes replace never with unknown for composition --- src/typedefs/ConstructorOptions.ts | 9 +++++---- src/typedefs/ConstructorOverrides.ts | 3 +-- test/unit/typedefs/PixiElements.test.tsx | 6 +++++- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/typedefs/ConstructorOptions.ts b/src/typedefs/ConstructorOptions.ts index f2921a93..441892f4 100644 --- a/src/typedefs/ConstructorOptions.ts +++ b/src/typedefs/ConstructorOptions.ts @@ -5,8 +5,9 @@ import type { ConstructorOverrides } from './ConstructorOverrides'; * @see https://github.com/pixijs/pixi-react/issues/500 */ export type ConstructorOptions any> = - T extends new (...args: any[]) => infer Instance - ? Instance extends keyof ConstructorOverrides - ? ConstructorOverrides[Instance] - : ConstructorParameters[0] + Extract extends [T, infer R] + ? unknown extends R + ? ConstructorParameters[0] + : R : unknown; + diff --git a/src/typedefs/ConstructorOverrides.ts b/src/typedefs/ConstructorOverrides.ts index 5e17aaeb..046ec053 100644 --- a/src/typedefs/ConstructorOverrides.ts +++ b/src/typedefs/ConstructorOverrides.ts @@ -22,5 +22,4 @@ export type ConstructorOverrides = | [typeof DisplacementFilter, DisplacementFilterOptions] | [typeof Filter, FilterOptions] | [typeof NoiseFilter, NoiseFilterOptions] - | [typeof Text, TextOptions] - | unknown; + | [typeof Text, TextOptions]; diff --git a/test/unit/typedefs/PixiElements.test.tsx b/test/unit/typedefs/PixiElements.test.tsx index cb82365e..fec13d7d 100644 --- a/test/unit/typedefs/PixiElements.test.tsx +++ b/test/unit/typedefs/PixiElements.test.tsx @@ -13,10 +13,11 @@ describe('PixiElements', () => { /* noop */ }} /> + ); - expect(elements.props.children).to.have.length(3); + expect(elements.props.children).to.have.length(4); expect(elements.props.children[0].type).to.equal('graphics'); expect(elements.props.children[0].props.draw).to.be.a('function'); @@ -27,5 +28,8 @@ describe('PixiElements', () => expect(elements.props.children[2].type).to.equal('alphaFilter'); expect(elements.props.children[2].props.alpha).to.equal(0.5); + + expect(elements.props.children[3].type).to.equal('pixiText'); + expect(elements.props.children[3].props.text).to.equal('Hello, World!'); }); });