diff --git a/src/types/PropsWithType.ts b/src/types/PropsWithType.ts index 2679a56..fc63273 100644 --- a/src/types/PropsWithType.ts +++ b/src/types/PropsWithType.ts @@ -16,6 +16,6 @@ * ``` */ // eslint-disable-next-line @typescript-eslint/no-type-alias -export type PropsWithType = keyof Pick = Exclude; +}[keyof O]>, undefined>; diff --git a/tests/types/PropsWithType.test.ts b/tests/types/PropsWithType.test.ts index edd9d26..d6b80c2 100644 --- a/tests/types/PropsWithType.test.ts +++ b/tests/types/PropsWithType.test.ts @@ -1,12 +1,14 @@ import { expect } from 'chai'; import { PropsWithType } from '../../src/index'; +import { isUndefined } from 'util'; describe('PropsWithType', () => { - // NOTE This test does not really check much at runtime. The real value is in the type + // NOTE These tests do not really check much at runtime. The real value is in the type // checking that happens by *using* the `PropsWithType` type in this test. If we break // the definition of `PropsWithType` so that it no longer selects the correct // properties, the TypeScript compiler will complain about this test. + it('allows property keys that have a given type', () => { interface TestType { readonly prop: string; @@ -25,4 +27,44 @@ describe('PropsWithType', () => { expect(getNumber(obj, 'additionalProp')).to.strictlyEqual(2); }); + it('correctly defines types for types that have optional params', () => { + interface TestType { + readonly prop: string; + readonly anotherProp: number; + readonly additionalProp?: number; + } + + function getNumber(from: TestType, field: PropsWithType): number { + // `field` will only be allowed to be `anotherProp` or `additionalProp`. Should + // note that `from[field]` is `number | undefined`. + const val = from[field]; + + return isUndefined(val) ? 0 : val; + } + + let obj: TestType = { prop: 'test', anotherProp: 1, additionalProp: 2 }; + + expect(getNumber(obj, 'anotherProp')).to.strictlyEqual(1); + expect(getNumber(obj, 'additionalProp')).to.strictlyEqual(2); + + // NOTE: leaving the following cases commented out as we don't have an automated way + // to test types. This package cannot ship with these uncommented as they report the + // error "X is declared but never used.ts(6196)". + + // Should be: "prop" + // type onlyStrings = PropsWithType; + + // Should be: "anotherProp" + // type onlyNumbers = PropsWithType; + + // Should be: "anotherProp" | "additionalProp" + // type numbersOrUndefineds = PropsWithType; + + // Should be: never + // type undefineds = PropsWithType; + + // Should be: never + // type booleans = PropsWithType; + }); + });