Skip to content

Commit

Permalink
feat(StrictOmit): Add StrictOmit (#35)
Browse files Browse the repository at this point in the history
* feat(StrictOmit): Add StrictOmit type

* test(StrictOmit): Add StrictOmit type test

* docs(StrictOmit): Add StrictOmit documentation
  • Loading branch information
haejunejung authored Aug 24, 2024
1 parent e7adb72 commit b277a5a
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 0 deletions.
9 changes: 9 additions & 0 deletions docs/.vitepress/en.mts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@ export default defineConfig({
{ text: 'Primitive', link: '/reference/basic/Primitive' },
],
},
{
text: 'Utilities',
items: [
{
text: 'StrictOmit',
link: '/reference/utilities/StrictOmit',
},
],
},
{
text: 'String',
items: [
Expand Down
9 changes: 9 additions & 0 deletions docs/.vitepress/ko.mts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,15 @@ export default defineConfig({
{ text: 'Primitive', link: '/ko/reference/basic/Primitive' },
],
},
{
text: 'Utilities',
items: [
{
text: 'StrictOmit',
link: '/ko/reference/utilities/StrictOmit',
},
],
},
{
text: 'String',
items: [
Expand Down
58 changes: 58 additions & 0 deletions docs/ko/reference/utilities/StrictOmit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# StrictOmit\<ObjectType, ExcludedKeys>

## 개요

이 타입은 TypeScript의 `Omit`유틸리티 타입의 더 엄격한 버전이에요.

`Omit`은 주어진 타입에 존재하지 않는 키의 생략도 허용하는 것과 달리, `StrictOmit`은 실제로 타입에 존재하는 키만 생략할 수 있도록 보장해요. 이를 통해 더 제어된 예측 가능한 타입 조작이 가능해지며, 존재하지 않는 키의 의도치 않은 생략을 방지할 수 있어요.

## 문법

```ts
type StrictOmit<
ObjectType extends object,
ExcludedKeys extends keyof ObjectType,
> = Pick<ObjectType, Exclude<keyof ObjectType, ExcludedKeys>>;
```

- **ObjectType**: 속성이 생략될 타입이에요.
- **ExcludedKeys**: 생략할 키들로, 반드시 `ObjectType`에 존재해야 해요.

## 예제

#### 예제 #1

```ts
type Example = {
a: number;
b: string;
c: boolean;
};

type StrictOmittedExample = StrictOmit<Example, 'c'>;
// Result: { a: number; b: string }
```

:::tip
팀에서 ESLint를 사용하고 `Omit` 대신 `StrictOmit`을 사용하도록 강제하려면, ESLint 설정을 통해 이를 감지할 수 있어요. `@typescript-eslint/ban-types` 규칙을 설정하여 `Omit`이 사용될 때 오류 메시지를 표시하게 함으로써, 개발자들이 `StrictOmit`을 사용하도록 유도할 수 있어요. 아래는 ESLint 설정 방법이에요.

```js
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
rules: {
// Include other relevant rules here
'@typescript-eslint/ban-types': [
'error',
{
types: {
Omit: 'Use StrictOmit instead',
},
extendsDefaults: true,
},
],
},
};
```

:::
61 changes: 61 additions & 0 deletions docs/reference/utilities/StrictOmit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# StrictOmit\<ObjectType, ExcludedKeys>

## Overview

This type is a stricter version of TypeScript's `Omit` utility type.

Unlike `Omit`, which allows omission of keys not present on the given type,
`StrictOmit` ensures that only keys actually present in the type can be omitted.
This provides a more controlled and predictable type manipulation, preventing
unintended omissions of non-existent keys.

## Syntax

```ts
type StrictOmit<
ObjectType extends object,
ExcludedKeys extends keyof ObjectType,
> = Pick<ObjectType, Exclude<keyof ObjectType, ExcludedKeys>>;
```

- **ObjectType**: The type from which properties will be omitted.
- **ExcludedKeys**: The keys to be omitted, which must be present in `ObjectType`.

## Examples

#### Example #1

```ts
type Example = {
a: number;
b: string;
c: boolean;
};

type StrictOmittedExample = StrictOmit<Example, 'c'>;
// Result: { a: number; b: string }
```

:::tip
If your team is using ESLint and wants to enforce the use of `StrictOmit` instead of the standard `Omit`, you can configure ESLint to help catch this. The `@typescript-eslint/ban-types` rule can be configured to display an error message when `Omit` is used, guiding developers to use `StirctOmit` instead. Here's how you can set up your ESLint configuration:

```js
module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
rules: {
// Include other relevant rules here
'@typescript-eslint/ban-types': [
'error',
{
types: {
Omit: 'Use StrictOmit instead',
},
extendsDefaults: true,
},
],
},
};
```

:::
1 change: 1 addition & 0 deletions source/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './predicate';
export * from './string';
export * from './special';
export * from './url-parser';
export * from './utilities';
35 changes: 35 additions & 0 deletions source/utilities/StrictOmit.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @description
* This type is a stricter version of TypeScript's `Omit` utility types.
*
* Unlike `Omit`, which allows omission of keys not present on the given type,
* `StrictOmit` ensures that only keys actually present in the type can be omitted.
* This provides a more controlled and predictable type manipulation, preventing
* unintended omissions of non-existent keys.
*
* @template {object} ObjectType - The type from which properties will be omitted.
* @template ExcludedKeys - The keys to be omitted, which must be present in `ObjectType`.
*
* @returns
* A type with the properties of `ObjectType`, excluding those specified in `ExcludedKeys`.
*
* @example
* type Example = {
* a: number;
* b: string;
* c: boolean;
* }
*
* // Omit can exclude keys not present on the type.
* type OmittedExample = Omit<Example, 'a' | 'noexistent'>;
* // Result: { b: string; c: boolean; }
*
* // StrictOmit enforces that only existing keys can be omitted.
* type StrictOmittedExample = StrictOmit<Example, 'a' | 'noexistent'>
* // Type '"a" | "noexistent"' does not satisfy the constraint 'keyof Example'.
* // Type '"noexistent"' is not assignable to type 'keyof Example'.
*/
export type StrictOmit<
ObjectType extends object,
ExcludedKeys extends keyof ObjectType,
> = Pick<ObjectType, Exclude<keyof ObjectType, ExcludedKeys>>;
1 change: 1 addition & 0 deletions source/utilities/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type { StrictOmit } from './StrictOmit';
16 changes: 16 additions & 0 deletions test-d/utilities/StrictOmit.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { StrictOmit } from '@/utilities';
import { expectType } from 'tsd';

declare function strictOmit<T extends object, K extends keyof T>(): StrictOmit<
T,
K
>;

type Example = {
a: number;
b: string;
c: boolean;
};

expectType<{ a: number; b: string }>(strictOmit<Example, 'c'>());
expectType<{}>(strictOmit<{ a: number }, 'a'>());

0 comments on commit b277a5a

Please sign in to comment.