programing

TypeScript에서 단일 속성을 옵션으로 설정

bestprogram 2023. 3. 28. 22:43

TypeScript에서 단일 속성을 옵션으로 설정

TypeScript 2.2에서는...

예를 들어 다음과 같은 유형의 사람이 있다고 가정합니다.

interface Person {
  name: string;
  hometown: string;
  nickname: string;
}

또한 사용자를 반환하지만 닉네임이 필요 없는 함수를 만들고 싶습니다.

function makePerson(input: ???): Person {
  return {...input, nickname: input.nickname || input.name};
}

의 유형은 무엇입니까?input? 와 같은 타입을 동적으로 지정하는 방법을 찾고 있습니다.Person을 제외하고nickname는 옵션입니다(nickname?: string | undefined지금까지 알아낸 것 중 가장 가까운 것은 다음과 같습니다.

type MakePersonInput = Partial<Person> & {
  name: string;
  hometown: string;
}

다만, 옵션 타입이 아닌, 필요한 타입을 모두 지정해야 하기 때문에, 이 타입을 찾고 있는 것은 아닙니다.

이와 같은 작업을 수행할 수도 있습니다. 일부 키만 사용할 수 있습니다.

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>

interface Person {
  name: string;
  hometown: string;
  nickname: string;
}

type MakePersonInput = PartialBy<Person, 'nickname'>

이것은 타입 스크립트 3.5+ 옵션 유틸리티 타입입니다.

type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>;

// and your use case
type MakePersonInput = Optional<Person, 'nickname'>

// and if you wanted to make the hometown optional as well
type MakePersonInput = Optional<Person, 'hometown' | 'nickname'>

플러그 앤 플레이 솔루션에 대해서는, 다음과 같은 뛰어난 패키지의 사용을 검토해 주세요.

npm i utility-types --save

다음으로 다음 항목을 사용합니다.

import { Optional } from 'utility-types';

type Person = {
  name: string;
  hometown: string;
  nickname: string;
}

type PersonWithOptionalNickname = Optional<Person, 'nickname'>;

// Expect:
//
// type PersonWithOptionalNickname {
//   name: string;
//   hometown: string;
//   nickname?: string;
// }

업데이트:

TypeScript 2.8 에서는, 조건 타입에 의해서 한층 더 간단하게 서포트되고 있습니다.지금까지 이 또한 이전 구현보다 더 신뢰할 수 있는 것으로 보입니다.

type Overwrite<T1, T2> = {
    [P in Exclude<keyof T1, keyof T2>]: T1[P]
} & T2;

interface Person {
  name: string;
  hometown: string;
  nickname: string;
}

type MakePersonInput = Overwrite<Person, {
  nickname?: string;
}>

function makePerson(input: MakePersonInput): Person {
  return {...input, nickname: input.nickname || input.name};
}

아까처럼MakePersonInput는 다음과 같습니다.

type MakePersonInput = {
    name: string;
    hometown: string;
} & {
    nickname?: string;
}

구식:

TypeScript 2.4.1에서는 GitHub 사용자 ahejlsberg가 스레드 온 타입 감산 방식으로 제안한 다른 옵션이 있는 것 같습니다.https://github.com/Microsoft/TypeScript/issues/12215#issuecomment-307871458

type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Overwrite<T, U> = { [P in Diff<keyof T, keyof U>]: T[P] } & U;

interface Person {
  name: string;
  hometown: string;
  nickname: string;
}
type MakePersonInput = Overwrite<Person, {
  nickname?: string
}>
function makePerson(input: MakePersonInput): Person {
  return {...input, nickname: input.nickname || input.name};
}

인텔리센스에 따르면MakePersonInput는 다음과 같습니다.

type MakePersonInput = {
    name: string;
    hometown: string;
} & {
    nickname?: string;
}

좀 웃기게 생겼지만 확실히 해냈죠.

안 좋은 쪽으로, 난 그걸 바라볼 필요가 있을 거야Diff어떻게 작동하는지 알기 전에 잠시 입력해 주세요.

type-fest 패키지에는 유틸리티가 있습니다.SetOptional- https://github.com/sindresorhus/type-fest/blob/main/source/set-optional.d.ts

import { SetOptional } from 'type-fest';

type PersonWithNicknameOptional = SetOptional<Person, 'nickname'>

라이브러리가 잘 관리되어 있고 최신 버전의 타이프 스크립트를 지원합니다.타이프 스크립트 프로젝트 IMO에 추가할 가치가 있습니다.

최신 버전의 타이프스크립트를 사용하는 경우 간단한 해결책은 다음과 같습니다.

function makePerson(input: Omit<Person, 'nickname'> & { nickname?: string }): Person {
  return {...input, nickname: input.nickname || input.name};
}

기본적으로 인터페이스에서 "nickname" 속성을 삭제하고 옵션으로 다시 추가합니다.

원래의 인터페이스와 동기하고 싶은 경우는, 다음의 조작을 실행할 수 있습니다.

Omit<Person, 'nickname'> & Partial<Pick<Person, 'nickname'>>

원래 인터페이스에서 "private" 프로펠러를 변경하면 경고가 표시됩니다.

네, 실제로 설명하고 있는 것은, 2개의 다른 「타입」의 사람(즉, 사람 타입)입니다.평범한 사람과 별명이 붙은 사람.

interface Person {
    name: string;
    hometown: string;
}

interface NicknamedPerson extends Person {
    nickname: string;
}

그런 다음 닉네임을 가진 사람이 아니라 단순히 사람을 원하는 경우에는 Person 인터페이스를 구현하면 됩니다.

1개의 사용자 인터페이스만을 유지할 필요가 있는 경우는, 닉네임이 없는 사용자에 대해서 다른 실장을 실시하는 방법도 있습니다.

interface Person {
  name: string;
  hometown: string;
  nickname: string;
}
class NicknamedPerson implements Person {
    constructor(public name: string, public hometown: string, public nickname: string) {}
}

class RegularPerson implements Person {
    nickname: string;
    constructor(public name: string, public hometown: string) {
        this.nickname = name;
    }
}

makePerson(input): Person {
     if(input.nickname != null) {
       return new NicknamedPerson(input.name, input.hometown, input.nickname);
     } else {
       return new RegularPerson(input.name, input.hometown);
     }
}

이렇게 하면 닉네임을 할당하고(닉네임이 없는 경우 사용자 이름만 해당) 사용자 인터페이스의 계약을 유지할 수 있습니다.이것은, 실제로, 인터페이스를 사용하는 방법에 관한 것입니다.닉네임을 가진 사람에 대해 코드가 신경을 쓰나요?그렇지 않다면, 첫 번째 제안이 더 나을 것입니다.

여러 번 조사해 본 결과, TypeScript에서는 불가능하다고 생각됩니다.아직이다. 하지만 확산/휴식 타입이 착륙할 때, 나는 그것이 구문을 따라 무엇인가가 될 것이라고 생각한다.{ ...Person, nickname?: string }.

지금은 좀 더 자세한 접근법으로 필요한 속성을 선언했습니다.

type MakePersonInput = Partial<Person> & {
  name: string;
  hometown: string;
};
function makePerson(input: MakePersonInput): Person {
  return {...input, nickname: input.nickname || input.name};
}

.MakePersonInputi whenever whenever whenever whenever whenever whenever whenever whenever whenever whenever whenever whenever whenever whenever Person 수 ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ, ㄴ.그것은, 에러 타입의 원인이 되기 때문입니다.makePerson.

언급URL : https://stackoverflow.com/questions/43159887/make-a-single-property-optional-in-typescript