mirror of
https://github.com/sindresorhus/type-fest.git
synced 2025-12-08 19:25:05 +00:00
Add ConditionalSimplify and ConditionalSimplifyDeep types (#442)
This commit is contained in:
parent
bbccfb88a0
commit
beaabe1821
32
source/conditional-simplify.d.ts
vendored
Normal file
32
source/conditional-simplify.d.ts
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
Simplifies a type while including and/or excluding certain types from being simplified. Useful to improve type hints shown in editors. And also to transform an interface into a type to aide with assignability.
|
||||
|
||||
This type is **experimental** and was introduced as a result of this {@link https://github.com/sindresorhus/type-fest/issues/436 issue}. It should be used with caution.
|
||||
|
||||
@internal
|
||||
@experimental
|
||||
@see Simplify
|
||||
@category Object
|
||||
*/
|
||||
export type ConditionalSimplify<Type, ExcludeType = never, IncludeType = unknown> = Type extends ExcludeType
|
||||
? Type
|
||||
: Type extends IncludeType
|
||||
? {[TypeKey in keyof Type]: Type[TypeKey]}
|
||||
: Type;
|
||||
|
||||
/**
|
||||
Recursively simplifies a type while including and/or excluding certain types from being simplified.
|
||||
|
||||
This type is **experimental** and was introduced as a result of this {@link https://github.com/sindresorhus/type-fest/issues/436 issue}. It should be used with caution.
|
||||
|
||||
See {@link ConditionalSimplify} for usages and examples.
|
||||
|
||||
@internal
|
||||
@experimental
|
||||
@category Object
|
||||
*/
|
||||
export type ConditionalSimplifyDeep<Type, ExcludeType = never, IncludeType = unknown> = Type extends ExcludeType
|
||||
? Type
|
||||
: Type extends IncludeType
|
||||
? {[TypeKey in keyof Type]: ConditionalSimplifyDeep<Type[TypeKey], ExcludeType, IncludeType>}
|
||||
: Type;
|
||||
81
test-d/conditional-simplify.ts
Normal file
81
test-d/conditional-simplify.ts
Normal file
@ -0,0 +1,81 @@
|
||||
import {expectError, expectType} from 'tsd';
|
||||
import type {ConditionalSimplify, ConditionalSimplifyDeep} from '../source/conditional-simplify';
|
||||
|
||||
type Position = {top: number; left: number};
|
||||
type Size = {width: number; height: number};
|
||||
|
||||
// In your editor, hovering over `PositionAndSizeSimplified` will show a simplified object with all the properties.
|
||||
type PositionAndSizeIntersection = Position & Size;
|
||||
type PositionAndSizeSimplified = ConditionalSimplify<PositionAndSizeIntersection>;
|
||||
|
||||
const position = {top: 120, left: 240};
|
||||
const size = {width: 480, height: 600};
|
||||
const positionAndSize = {...position, ...size};
|
||||
expectType<PositionAndSizeSimplified>(positionAndSize);
|
||||
|
||||
// Exclude function type to be simplified.
|
||||
type SomeFunction = (type: string) => string;
|
||||
type SimplifiedFunctionFail = ConditionalSimplify<SomeFunction>; // Return '{}'
|
||||
type SimplifiedFunctionPass = ConditionalSimplify<SomeFunction, Function>; // Return '(type: string) => string'
|
||||
|
||||
declare const simplifiedFunctionFail: SimplifiedFunctionFail;
|
||||
declare const simplifiedFunctionPass: SimplifiedFunctionPass;
|
||||
|
||||
expectError<SomeFunction>(simplifiedFunctionFail);
|
||||
expectType<SomeFunction>(simplifiedFunctionPass);
|
||||
|
||||
// Should simplify interface deeply.
|
||||
interface SomeNode {
|
||||
parent: PositionAndSizeIntersection;
|
||||
childs: Array<{parent: PositionAndSizeIntersection}>;
|
||||
}
|
||||
|
||||
// In your editor, hovering over `SomeNodeSimplified` will show a simplified object with all the properties.
|
||||
type SomeNodeSimplified = ConditionalSimplifyDeep<SomeNode>;
|
||||
|
||||
const someNode = {parent: positionAndSize, childs: [{parent: positionAndSize}, {parent: positionAndSize}]};
|
||||
expectType<SomeNodeSimplified>(someNode);
|
||||
|
||||
// Should simplify interface deeply excluding Function type.
|
||||
interface MovablePosition extends Position {
|
||||
move(position: Position): Position;
|
||||
}
|
||||
|
||||
interface MovableCollection {
|
||||
position: MovablePosition;
|
||||
top: {position: MovablePosition; size: Size};
|
||||
left: {position: MovablePosition; size: Size};
|
||||
}
|
||||
|
||||
type MovableNodeSimplifiedFail = ConditionalSimplifyDeep<MovableCollection>;
|
||||
type MovableNodeSimplifiedPass = ConditionalSimplifyDeep<MovableCollection, Function>;
|
||||
|
||||
declare const movableNodeSimplifiedFail: MovableNodeSimplifiedFail;
|
||||
declare const movableNodeSimplifiedPass: MovableNodeSimplifiedPass;
|
||||
|
||||
expectError<MovableCollection>(movableNodeSimplifiedFail);
|
||||
expectType<MovableCollection>(movableNodeSimplifiedPass);
|
||||
|
||||
const movablePosition = {
|
||||
top: 42,
|
||||
left: 42,
|
||||
move(position: Position) {
|
||||
return position;
|
||||
},
|
||||
};
|
||||
|
||||
const movableNode = {
|
||||
position: movablePosition,
|
||||
top: {position: movablePosition, size},
|
||||
left: {position: movablePosition, size},
|
||||
};
|
||||
|
||||
expectType<MovableNodeSimplifiedPass>(movableNode);
|
||||
|
||||
// Should exclude `Function` and `Size` type (mainly visual, mouse over the statement).
|
||||
type ExcludeFunctionAndSize1 = ConditionalSimplifyDeep<MovableCollection, Function | Size>;
|
||||
expectType<ExcludeFunctionAndSize1>(movableNode);
|
||||
|
||||
// Same as above but using `IncludeType` parameter (mainly visual, mouse over the statement).
|
||||
type ExcludeFunctionAndSize2 = ConditionalSimplifyDeep<MovableCollection, Function, MovableCollection | Position>;
|
||||
expectType<ExcludeFunctionAndSize2>(movableNode);
|
||||
Loading…
x
Reference in New Issue
Block a user