source

Typescript d.ts 파일에 정의된 인터페이스 속성 유형을 재정의하고 있습니다.

itover 2022. 12. 21. 22:31
반응형

Typescript d.ts 파일에 정의된 인터페이스 속성 유형을 재정의하고 있습니다.

되어 있는 ?*.d.ts★★★★★★★★★★★★★★★★★★?

예를 들어 다음과 같습니다.x.d.ts되어 있습니다.

interface A {
  property: number;
}

내가 쓰는 타이프스크립트 파일에서 변경하고 싶다.

interface A {
  property: Object;
}

이마저도 효과가 있을 것이다.

interface B extends A {
  property: Object;
}

이 접근방식이 효과가 있을까요?시스템을 사용해보니 작동이 되지 않았다.그게 가능한지 확인하고 싶으신 건가요?

먼저 필드를 필터링한 후 결합하는 방법을 사용합니다.

참조 형식에서 속성 제외

interface A {
    x: string
}

export type B = Omit<A, 'x'> & { x: number };

인터페이스:

interface A {
    x: string
}

interface B extends Omit<A, 'x'> {
  x: number
}
 type ModifiedType = Modify<OriginalType, {
  a: number;
  b: number;
}>
 
interface ModifiedInterface extends Modify<OriginalType, {
  a: number;
  b: number;
}> {}

ZSKYcat에서 영감을 얻어 extends Omit츠키다

type Modify<T, R> = Omit<T, keyof R> & R;

// before typescript@3.5
type Modify<T, R> = Pick<T, Exclude<keyof T, keyof R>> & R

예:

interface OriginalInterface {
  a: string;
  b: boolean;
  c: number;
}

type ModifiedType  = Modify<OriginalInterface , {
  a: number;
  b: number;
}>

// ModifiedType = { a: number; b: number; c: number; }

단계별 진행:

type R0 = Omit<OriginalType, 'a' | 'b'>        // { c: number; }
type R1 = R0 & {a: number, b: number }         // { a: number; b: number; c: number; }

type T0 = Exclude<'a' | 'b' | 'c' , 'a' | 'b'> // 'c'
type T1 = Pick<OriginalType, T0>               // { c: number; }
type T2 = T1 & {a: number, b: number }         // { a: number; b: number; c: number; }

TypeScript 유틸리티 유형


v2.0 상세 변경

interface Original {
  a: {
    b: string
    d: {
      e: string // <- will be changed
    }
  }
  f: number
}

interface Overrides {
  a: {
    d: {
      e: number
      f: number // <- new key
    }
  }
  b: {         // <- new key
    c: number
  }
}

type ModifiedType = ModifyDeep<Original, Overrides>
interface ModifiedInterface extends ModifyDeep<Original, Overrides> {}
// ModifiedType =
{
  a: {
    b: string
    d: {
      e: number
      f: number
    }
  }
  b: {
    c: number
  }
  f: number
}

★★ModifyDeep 이하에 나타냅니다.

기존 속성의 유형은 변경할 수 없습니다.

속성을 추가할 수 있습니다.

interface A {
    newProperty: any;
}

그러나 기존 유형의 변경:

interface A {
    property: any;
}

에러가 발생합니다.

후속 변수 선언의 유형은 같아야 합니다.변수 'property'는 'number' 유형이어야 하지만 여기에는 'any' 유형이 있습니다.

물론 기존 인터페이스를 확장하는 자체 인터페이스를 가질 수 있습니다.이 경우 유형을 호환되는 유형으로만 재정의할 수 있습니다. 예를 들어 다음과 같습니다.

interface A {
    x: string | number;
}

interface B extends A {
    x: number;
}

아마 ' 쪽인가', '어느 쪽인가', '어느 쪽인가'는 하지 않는 것이 것 .Object대신 「」를 해 주세요.any.

유형의 문서에는 다음과 같이 기술되어 있습니다.

any type은 기존 JavaScript를 사용하는 강력한 방법이며 컴파일 중에 타입 체크를 단계적으로 선택 또는 해제할 수 있습니다.오브젝트도 다른 언어에서와 마찬가지로 비슷한 역할을 할 것으로 예상할 수 있습니다.그러나 Object 유형의 변수에서는 값만 할당할 수 있습니다. 실제로 존재하는 변수라도 임의 메서드를 호출할 없습니다.

let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.

나 같은 게으른 사람들을 위한 짧은 대답:

type Overrided = Omit<YourInterface, 'overrideField'> & { overrideField: <type> }; 
interface Overrided extends Omit<YourInterface, 'overrideField'> {
  overrideField: <type>
}

@zSkycat의 답변을 조금 확장하면 두 가지 오브젝트 유형을 받아들이고 두 번째 오브젝트의 멤버가 첫 번째 멤버를 덮어쓰고 병합된 유형을 반환하는 범용을 만들 수 있습니다.

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;

interface A {
    name: string;
    color?: string;
}

// redefine name to be string | number
type B = Merge<A, {
    name: string | number;
    favorite?: boolean;
}>;

let one: A = {
    name: 'asdf',
    color: 'blue'
};

// A can become B because the types are all compatible
let two: B = one;

let three: B = {
    name: 1
};

three.name = 'Bee';
three.favorite = true;
three.color = 'green';

// B cannot become A because the type of name (string | number) isn't compatible
// with A even though the value is a string
// Error: Type {...} is not assignable to type A
let four: A = three;

Omit"CHANGE: "CHANGE:

interface A {
  a: number;
  b: number;
}

interface B extends Omit<A, 'a'> {
  a: boolean;
}

네스트된 인터페이스를 간단하게 덮어쓸 수 있는 타입을 작성했습니다.

type ModifyDeep<A extends AnyObject, B extends DeepPartialAny<A>> = {
  [K in keyof A]: B[K] extends never
    ? A[K]
    : B[K] extends AnyObject
      ? ModifyDeep<A[K], B[K]>
      : B[K]
} & (A extends AnyObject ? Omit<B, keyof A> : A)

/** Makes each property optional and turns each leaf property into any, allowing for type overrides by narrowing any. */
type DeepPartialAny<T> = {
  [P in keyof T]?: T[P] extends AnyObject ? DeepPartialAny<T[P]> : any
}

type AnyObject = Record<string, any>

그런 다음 다음과 같이 사용할 수 있습니다.

interface Original {
  a: {
    b: string
    d: {
      e: string // <- will be changed
    }
  }
  f: number
}

interface Overrides {
  a: {
    d: {
      e: number
      f: number // <- new key
    }
  }
  b: {         // <- new key
    c: number
  }
}

type ModifiedType = ModifyDeep<Original, Overrides>
interface ModifiedInterface extends ModifyDeep<Original, Overrides> {}
// ModifiedType =
{
  a: {
    b: string
    d: {
      e: number
      f: number
    }
  }
  b: {
    c: number
  }
  f: number
}

, 간단히 , , , , , , , , , , ,.extendNitzan의 답변처럼 완벽하게 작동합니다.

interface A {
    x: string | number;
}

interface B extends A {
    x: number;
}

확대하거나 일반적으로 유형을 재정의하기 위해 Zskycat의 솔루션을 수행할 수 있습니다.

interface A {
    x: string
}

export type B = Omit<A, 'x'> & { x: number };

가 " "일 "A.A의 시)Omit.

예.

interface A extends Record<string | number, number | string | boolean> {
    x: string;
    y: boolean;
}

export type B = Omit<A, 'x'> & { x: number };

let b: B = { x: 2, y: "hi" }; // no error on b.y! 

이,입니다.Omit으로만 Exclude<keyof A, 'x'>인 키가 키string | number저희 같은 경우에는요.so,는,B될 것이다{x: number; }다음 유형의 추가 자산을 받아들입니다.number | string | boolean.


는 다른 을 .OverrideProps유틸리티 타입은 다음과 같습니다.

type OverrideProps<M, N> = { [P in keyof M]: P extends keyof N ? N[P] : M[P] };

예:

type OverrideProps<M, N> = { [P in keyof M]: P extends keyof N ? N[P] : M[P] };

interface A extends Record<string | number, number | string | boolean> {
    x: string;
    y: boolean;
}

export type B = OverrideProps<A, { x: number }>;

let b: B = { x: 2, y: "hi" }; // error: b.y should be boolean!

내가 같은 사건을 해결할 가능성을 조사하는데 하루를 보낸다는 게 재밌다.이 방법으로는 할 수 없다는 것을 알았습니다.

// a.ts - module
export interface A {
    x: string | any;
}

// b.ts - module
import {A} from './a';

type SomeOtherType = {
  coolStuff: number
}

interface B extends A {
    x: SomeOtherType;
}

원인 A 모듈이 응용 프로그램에서 사용 가능한 모든 유형을 인식하지 못할 수 있습니다.모든 곳에서 온 모든 것을 포팅하고 코드를 이렇게 하는 것은 꽤 지루합니다.

export interface A {
    x: A | B | C | D ... Million Types Later
}

자동 완성이 제대로 작동하려면 나중에 유형을 정의해야 합니다.


약간의 속임수를 쓸 수 있습니다.

// a.ts - module
export interface A {
    x: string;
}

재정의가 필요하지 않은 경우 자동 완료를 허용하는 일부 유형을 기본적으로 그대로 둡니다.

그리고나서

// b.ts - module
import {A} from './a';

type SomeOtherType = {
  coolStuff: number
}

// @ts-ignore
interface B extends A {
    x: SomeOtherType;
}

서 '인 예외'를 무효로 합니다.@ts-ignore은 모든 이 예상대로.그리고 재밌는 건 모든 게 예상대로 되는 거야

x코드를 좀 더 엄격하게 할 수 있게 해주십시오., 속성 같은 수 .

2020년 3월 4.1) 버전이 지원한다고 합니다.interfaced.tsfilename을 클릭합니다.

// in test.d.ts

interface A {
  a: string
}

export interface B extends A {
  a: number
}

// in any ts file
import { B } from 'test.d.ts'

// this will work
const test: B = { a: 3 }

// this will not work
const test1: B = { a: "3" }

이것을 실시하기 위해서 범용 유틸리티 타입이 필요한 경우는, 다음의 솔루션을 생각해 냈습니다.

/**
 * Returns object T, but with T[K] overridden to type U.
 * @example
 * type MyObject = { a: number, b: string }
 * OverrideProperty<MyObject, "a", string> // returns { a: string, b: string }
 */
export type OverrideProperty<T, K extends keyof T, U> = Omit<T, K> & { [P in keyof Pick<T, K>]: U };

이게 필요했어요 제 경우엔, 덮어쓸 수 있는 열쇠가 범용 그 자체였기 때문이죠

★★★가Omit준비는 유형에서 속성 제외를 참조하십시오.

기존 속성의 유형만 변경하고 삭제하지 않는 경우 &로 충분합니다.

// Style that accepts both number and percent(string)
type BoxStyle = {
  height?: string | number,
  width?: string | number,
  padding?: string | number,
  borderRadius?: string | number,
}

// These are both valid
const box1: BoxStyle = {height: '20%', width: '20%', padding: 0, borderRadius: 5}
const box2: BoxStyle = {height: 85, width: 85, padding: 0, borderRadius: 5}

// Override height and width to be only numbers
type BoxStyleNumeric = BoxStyle & {
  height?: number,
  width?: number,
}

// This is still valid
const box3: BoxStyleNumeric = {height: 85, width: 85, padding: 0, borderRadius: 5}

// This is not valid anymore
const box4: BoxStyleNumeric = {height: '20%', width: '20%', padding: 0, borderRadius: 5}

Qwerty의 Modify 유틸리티 유형 솔루션을 확장하여 키를 제한합니다.R T를 추가합니다.

export type Modify<T, R extends Partial<Record<keyof T, any>>> = Omit<T, keyof R> & R;

메모: 이 답변에서 사용하고 있는 구문이 이전 답변이 작성되었을 때 사용 가능했는지는 모르겠지만, 이 질문에서 언급한 예를 해결하는 방법은 이 방법이 낫다고 생각합니다.


이 항목(인터페이스 속성 덮어쓰기)과 관련된 몇 가지 문제가 있었습니다.이 문제는 다음과 같습니다.

  1. 먼저 사용할 수 있는 유형의 범용 인터페이스를 만듭니다.

또한, 선택 가능.default에서 볼 수 있듯이 범용 파라미터의 값<T extends number | SOME_OBJECT = number>

type SOME_OBJECT = { foo: "bar" }

interface INTERFACE_A <T extends number | SOME_OBJECT = number> {
  property: T;
}
  1. 그런 다음 일반 매개 변수에 값을 전달(또는 생략하고 기본값 사용)하여 해당 계약에 따라 새 유형을 생성할 수 있습니다.
type A_NUMBER = INTERFACE_A;                   // USES THE default = number TYPE. SAME AS INTERFACE_A<number>
type A_SOME_OBJECT = INTERFACE_A<SOME_OBJECT>  // MAKES { property: SOME_OBJECT }

결과는 다음과 같습니다.

const aNumber: A_NUMBER = {
    property: 111  // THIS EXPECTS A NUMBER
}

const anObject: A_SOME_OBJECT = {
    property: {   // THIS EXPECTS SOME_OBJECT
        foo: "bar"
    }
}

활자놀이터

언급URL : https://stackoverflow.com/questions/41285211/overriding-interface-property-type-defined-in-typescript-d-ts-file

반응형