source

Typescript 인터페이스 기본값

nicesource 2023. 3. 20. 23:20
반응형

Typescript 인터페이스 기본값

TypeScript에는 다음과 같은 인터페이스가 있습니다.

interface IX {
    a: string,
    b: any,
    c: AnotherType
}

해당 유형의 변수를 선언하고 모든 속성을 초기화합니다.

let x: IX = {
    a: 'abc',
    b: null,
    c: null
}

그런 다음 나중에 init 함수에서 실제 값을 할당합니다.

x.a = 'xyz'
x.b = 123
x.c = new AnotherType()

그러나 개체를 선언할 때 각 속성에 대해 기본값 null 값을 여러 개 지정해야 하는 것은 좋아하지 않습니다.공급하지 않은 속성을 null로 기본 설정하도록 인터페이스에 지시할 수 있습니까?어떻게 하면 이 일을 할 수 있을까요?

let x: IX = {
    a: 'abc'
}

컴파일러 에러는 표시되지 않습니다.지금 그게 말해주고 있어

TS2322: 유형 '{}'은 유형 'IX'에 할당할 수 없습니다.유형 '{}'에 속성 'b'가 없습니다.

공급하지 않은 속성을 null로 기본 설정하도록 인터페이스에 지시할 수 있습니까?내가 왜 이걸 할 수 있을까?

아니요. 인터페이스 또는 형식 별칭은 컴파일 시간에만 사용할 수 있으며 기본값에는 런타임 지원이 필요하므로 기본값을 제공할 수 없습니다.

대안

, 되지 않은 로 ", " " 입니다.undefined자바스크립트옵션으로서 마킹할 수 있습니다.

interface IX {
  a: string,
  b?: any,
  c?: AnotherType
}

에서 작성 시 은 " " " " 입니다.a:

let x: IX = {
    a: 'abc'
};

필요에 따라 값을 지정할 수 있습니다.

x.a = 'xyz'
x.b = 123
x.c = new AnotherType()

인터페이스에서는 기본값을 설정할 수 없지만 옵션 속성을 사용하여 원하는 작업을 수행할 수 있습니다.

인터페이스를 다음과 같이 변경합니다.

interface IX {
    a: string,
    b?: any,
    c?: AnotherType
}

다음 작업을 수행할 수 있습니다.

let x: IX = {
    a: 'abc'
}

하여 기본 을 "Default" 에 합니다.x.b ★★★★★★★★★★★★★★★★★」x.c이 속성들이 설정되지 않은 경우.

@은 @Timar에게 딱 @Timar의 은 @Timar에게 딱 .null디폴트값(요구된 값)이 있습니다.다른 디폴트값을 사용할 수 있는 또 다른 간단한 솔루션이 있습니다.옵션 인터페이스와 기본값을 포함하는 상수를 정의합니다. 생성자에서 분산 연산자를 사용하여 다음을 설정합니다.options variable( 변수)

interface IXOptions {
    a?: string,
    b?: any,
    c?: number
}

const XDefaults: IXOptions = {
    a: "default",
    b: null,
    c: 1
}

export class ClassX {
    private options: IXOptions;

    constructor(XOptions: IXOptions) {
        this.options = { ...XDefaults, ...XOptions };
    }

    public printOptions(): void {
        console.log(this.options.a);
        console.log(this.options.b);
        console.log(this.options.c);
    }
}

이 클래스는 다음과 같이 사용할 수 있습니다.

const x = new ClassX({ a: "set" });
x.printOptions();

출력:

set
null
1

클래스를 사용하여 인터페이스를 구현하고 컨스트럭터의 멤버 초기화를 처리할 수 있습니다.

class IXClass implements IX {
    a: string;
    b: any;
    c: AnotherType;

    constructor(obj: IX);
    constructor(a: string, b: any, c: AnotherType);
    constructor() {
        if (arguments.length == 1) {
            this.a = arguments[0].a;
            this.b = arguments[0].b;
            this.c = arguments[0].c;
        } else {
            this.a = arguments[0];
            this.b = arguments[1];
            this.c = arguments[2];
        }
    }
}

또 다른 접근법은 공장 기능을 사용하는 것입니다.

function ixFactory(a: string, b: any, c: AnotherType): IX {
    return {
        a: a,
        b: b,
        c: c
    }
}

그 후, 다음과 같이 할 수 있습니다.

var ix: IX = null;
...

ix = new IXClass(...);
// or
ix = ixFactory(...);

.Partial매뉴얼에 기재되어 있는 맵유형:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html

이 예에서는 다음과 같이 됩니다.

interface IX {
    a: string;
    b: any;
    c: AnotherType;
}

let x: Partial<IX> = {
    a: 'abc'
}

다음 패턴을 사용합니다.

유형 " " " " 를 만듭니다.Defaults<T>:

type OptionalKeys<T> = { [K in keyof T]-?: {} extends Pick<T, K> ? K : never }[keyof T];
type Defaults<T> = Required<Pick<T, OptionalKeys<T>>>

옵션/기본값으로 클래스 선언:

// options passed to class constructor
export interface Options {
    a: string,
    b?: any,
    c?: number
}

// defaults
const defaults: Defaults<Options> = {
    b: null,
    c: 1
};

export class MyClass {
    // all options in class must have values
    options: Required<Options>;

    constructor(options: Options) {
        // merge passed options and defaults
        this.options = Object.assign({}, defaults, options);
    }
}

클래스 인스턴스 만들기:

const myClass = new MyClass({
    a: 'hello',
    b: true,
});

console.log(myClass.options);
// { a: 'hello', b: true, c: 1 }

인터페이스는 컴파일 시에만 존재하기 때문에 인터페이스에 대한 기본값은 사용할 수 없습니다.

대체 솔루션:

여기에는 XI 인터페이스를 구현하는 개체를 반환하는 공장 방식을 사용할 수 있습니다.

예:

class AnotherType {}

interface IX {
    a: string,
    b: any,
    c: AnotherType | null
}

function makeIX (): IX {
    return {
    a: 'abc',
    b: null,
    c: null
    }
}

const x = makeIX();

x.a = 'xyz';
x.b = 123;
x.c = new AnotherType();

하여 제가 은 두 가지 로 만든 입니다.AnotherType | null컴파일러 에러가 발생하지 않게 하려면 이 에러가 필요합니다(이 에러는, null을 속성 c 로 초기화한 예에서도 발생하고 있습니다).

파라미터가 많은 경우 사용자가 특정 순서가 아닌 소수의 파라미터만 삽입할 수 있도록 하는 것이 가장 좋습니다.

예를 들어, 잘못된 관행:

foo(a?, b=1, c=99, d=88, e?)
foo(null, null, null, 3)

실제로 필요한 파라미터보다 먼저 모든 파라미터를 지정해야 하기 때문에 (d)

바람직한 사용 방법은 다음과 같습니다.

foo({d=3})

그 방법은 인터페이스를 통해서입니다.파라미터는 다음과 같은 인터페이스로 정의해야 합니다.

interface Arguments {
    a?;
    b?; 
    c?;
    d?;
    e?;
}

그리고 함수를 다음과 같이 정의합니다.

foo(arguments: Arguments)

인터페이스 변수는 기본값을 가져올 수 없습니다.기본값은 어떻게 정의해야 합니까?

인터페이스 전체에 대해 기본값을 정의합니다.

foo({
        a,
        b=1,
        c=99,
        d=88,
        e                    
    }: Arguments)

사용자가 합격하면:

foo({d=3})

실제 파라미터는 다음과 같습니다.

{
    a,
    b=1,
    c=99,
    d=3,
    e                    
}

인터페이스를 선언하지 않는 다른 옵션은 다음과 같습니다.

foo({
        a=undefined,
        b=1,
        c=99,
        d=88,
        e=undefined                    
    })

Follow Up: 이전 함수 정의에서는 파라미터 객체의 필드에 대한 기본값을 정의하지만 객체 자체에 대한 기본값은 정의하지 않습니다.따라서 추출 오류가 발생합니다(예:Cannot read property 'b' of undefined 다음의 로부터, 「다음에」, 「다음에」를 참조해 주세요.

foo()

다음 두 가지 해결 방법이 있습니다.

1.

const defaultObject = {a=undefined, b=1, c=99, d=88, e=undefined}
function foo({a=defaultObject.a, b=defaultObject.b, c=defaultObject.c, d=defaultObject.d, e=defaultObject.e} = defaultObject)
function foo(object = {}) {
    object = { b=1, c=99, d=88, ...object }
    //Continue the function code..
}

폴로업: 타입과 디폴트값이 필요한 경우(인터페이스를 선언하고 싶지 않은 경우) 다음과 같이 기술할 수 있습니다.

function foo(params: {a?: string, b?: number, c?: number, d?: number, e?: string}) {
    params = { b:1, c:99, d:88, ...params }
    //Continue the function code..
}

나는 내가 도달한 것보다 더 나은 방법을 찾다가 이것을 우연히 발견했다.답을 읽고 시험해 본 결과, 다른 답변이 간결하게 느껴지지 않는 만큼, 제가 하고 있는 것을 게재할 가치가 있다고 생각했습니다.새로운 인터페이스를 설정할 때마다 적은 양의 코드만 작성하면 되는 것이 중요했습니다.나는...로 정했어요

커스텀 범용 deepCopy 함수 사용:

deepCopy = <T extends {}>(input: any): T => {
  return JSON.parse(JSON.stringify(input));
};

인터페이스 정의

interface IX {
    a: string;
    b: any;
    c: AnotherType;
}

... 디폴트를 다른 Const로 정의합니다.

const XDef : IX = {
    a: '',
    b: null,
    c: null,
};

다음으로 다음과 같이 초기화합니다.

let x : IX = deepCopy(XDef);

그것만 있으면 돼

하지만..

루트 요소를 커스텀 초기화하려면 deepCopy 함수를 변경하여 커스텀 기본값을 사용할 수 있습니다.기능은 다음과 같습니다.

deepCopyAssign = <T extends {}>(input: any, rootOverwrites?: any): T => {
  return JSON.parse(JSON.stringify({ ...input, ...rootOverwrites }));
};

대신 다음과 같이 호출할 수 있습니다.

let x : IX = deepCopyAssign(XDef, { a:'customInitValue' } );

다른 선호하는 딥 카피 방법은 모두 사용할 수 있습니다.얕은 복사만 필요한 경우 Object.assign으로 충분하며 유틸리티는 필요 없습니다.deepCopy또는deepCopyAssign기능.

let x : IX = object.assign({}, XDef, { a:'customInitValue' });

이미 알려진 문제

  • 이 가장으로 깊이 할당되지는 않지만 수정하는 것은 그리 어렵지 않습니다.deepCopyAssign할당하기 전에 유형을 반복하고 확인합니다.
  • 해석/문자열화 프로세스에 의해 함수 및 참조가 손실됩니다.내 업무에는 그것들이 필요없고 작전부도 필요없었다.
  • 커스텀 초기화 값은 실행 시 체크된 IDE 또는 타입에 의해 암시되지 않습니다.

솔루션:

입력 문제를 수정하기 위해 Object.assign 위에 래퍼를 만들었습니다.

export function assign<T>(...args: T[] | Partial<T>[]): T {
  return Object.assign.apply(Object, [{}, ...args]);
}

사용방법:

env.base.ts

export interface EnvironmentValues {
export interface EnvironmentValues {
  isBrowser: boolean;
  apiURL: string;
}

export const enviromentBaseValues: Partial<EnvironmentValues> = {
  isBrowser: typeof window !== 'undefined',
};

export default enviromentBaseValues;

env.dev.ts

import { EnvironmentValues, enviromentBaseValues } from './env.base';
import { assign } from '../utilities';

export const enviromentDevValues: EnvironmentValues = assign<EnvironmentValues>(
  {
    apiURL: '/api',
  },
  enviromentBaseValues
);

export default enviromentDevValues;

2개의 다른 설정을 사용할 수 있습니다.하나는 옵션 속성(기본값)이 있는 입력으로, 다른 하나는 필수 속성만 있는 입력입니다.이 기능은 다음과 같이 편리하게 사용할 수 있습니다.&그리고.Required:

interface DefaultedFuncConfig {
  b?: boolean;
}

interface MandatoryFuncConfig {
  a: boolean;
}

export type FuncConfig = MandatoryFuncConfig & DefaultedFuncConfig;
 
export const func = (config: FuncConfig): Required<FuncConfig> => ({
  b: true,
  ...config
});

// will compile
func({ a: true });
func({ a: true, b: true });

// will error
func({ b: true });
func({});

지금 이 상황을 헤쳐나가고 있어.를 사용하다class대신interface.

class IX {
  a: String = '';
  b?: any;
  c: Cee = new Cee();
}

class Cee {
  c: String = 'c';
  e: String = 'e';
}

리액트 컴포넌트에 이게 필요했어요

왼쪽 값이 Null 또는 Undefined인 경우 기본값을 할당하는 Nullish 병합 연산자를 사용할 수 있습니다.

interface IX {
    a: string,
    b?: any,
    c?: AnotherType
}

const ixFunction: React.FC<IX> = (props) => {
  console.log(props.b?? "DefaultValue")
}

그러나 이것은 변수를 한 곳에서만 사용하려는 경우에만 작동합니다.

케이스와 용도에 따라 다릅니다.일반적으로 TypeScript에서는 인터페이스의 기본값은 없습니다.

기본값을 사용하지 않는 경우
신고하실 수 있습니다.x다음과 같이 합니다.

let x: IX | undefined; // declaration: x = undefined

다음으로 init 함수에서 실제 값을 설정할 수 있습니다.

x = {
    a: 'xyz'
    b: 123
    c: new AnotherType()
};

이렇게 해서x정의되지 않거나 정의할 수 있습니다.undefined는 오브젝트가 불필요한 경우 기본값을 설정하지 않고 초기화되지 않았음을 나타냅니다.이것은 "쓰레기"를 정의하는 것보다 로지적으로 더 낫다.

개체를 부분적으로 할당하는 경우:
다음과 같은 선택적 속성을 사용하여 유형을 정의할 수 있습니다.

interface IX {
    a: string,
    b?: any,
    c?: AnotherType
}

이 경우 설정만 하면 됩니다.a은 '아까보다'로되어 있습니다?, 이며, 「」, 「」, 「」, 「」, 「」를 의미합니다.undefined디폴트값으로 설정합니다.

아니면 심지어

let x: Partial<IX> = { ... }

그러면 모든 필드가 선택사항이 됩니다.

어떤 경우에도 기본값으로 사용할 수 있습니다.사용 사례에 따라 다릅니다.

또한 기본 속성 값으로 개체를 반환하는 도우미 메서드/함수를 사용할 수 있습니다.이 경우 필요에 따라 발신자 코드가 기본값을 덮어쓸 수 있습니다.그것이 제가 현재 진행 중인 프로젝트에서 같은 질문에 직면했기 때문에 제가 따르고 있는 접근법입니다.이와 같이 기본 속성 값 개체를 코딩하는 것은 일회성 문제이며, 전체 응용 프로그램에서 이 개체를 재사용할 수 있습니다.

또 다른 방법은 https://www.npmjs.com/package/merge 를 사용하는 것입니다.
이것은 마지막 답과 같지만 좀 더 깔끔하다.

머지를 인스톨 합니다.

yarn add -D merge

다음으로 몇 가지 옵션을 사용하여 인터페이스를 만듭니다.
이걸 ㅇㅇㅇㅇㅇㅇㅇㅇㅇ에 요.
./types/index.ts.

export interface ExampleOpts {
    opt1: string,
    opt2: string,
    opt3: string,
}

은 기본 설정 .
수도 , 그 해서, 이렇게 , 이렇게 해서, 같은 파일에 수 .
./config/index.ts.

import { ExampleOpts } from '../types'

// Defaults
export const ExampleOptsDefault : ExampleOpts = {
    opt1: 'default value 1',
    opt2: 'default value 2',
    opt3: 'default value 3',
}

은 '다 같이 '의 .
./index.ts.

import { ExampleOpts } from './types'
import { ExampleOptsDefault } from './config'
import merge from 'merge'

// The ? makes the parameter optional
export function test1(options?: ExampleOpts) {
    // merge tries to load in the defaults first, then options next if it's defined
    const merged_opts: ExampleOpts = merge.recursive(ExampleOptsDefault, options)
    // log the result to the console
    console.log(merged_opts)
}

또 다른 방법은 Pick 유틸리티 유형을 사용하여 필요한 속성을 선택하는 것입니다.

interface IX {
    a: string,
    b: any,
    c: AnotherType
}

let x: Pick<IX, 'a'> = {
    a: 'abc'
}

그런 다음 실제 IX 개체를 선언할 때 다음과 같이 기본값을 새 값과 병합합니다.

const newX: IX = {
    ...x,
    b: 'b',
    c: () => {}
}

이 답변은 "How To Up A Type Script Interface Default Value?"에서 가져온 것입니다.

언급URL : https://stackoverflow.com/questions/35074365/typescript-interface-default-values

반응형