IT

TS2322를 수정하는 방법: "다른 유형의 구속조건 'object'로 인스턴스화할 수 있습니다."

itgroup 2023. 2. 22. 21:43
반응형

TS2322를 수정하는 방법: "다른 유형의 구속조건 'object'로 인스턴스화할 수 있습니다."

A의 재귀 유형에 유형 검사 오류가 있습니다.

react-jss style 객체에 활자를 쓰려고 합니다.

type StylesFn<P extends object> = (
  props: P
) => CSS.Properties<JssValue<P>> | number | string;

type JssValue<P extends object> =
  | string
  | number
  | Array<string | number>
  | StylesFn<P>;

// @ts-ignore
interface StylesObject<K extends string = any, P extends object = {}>
  extends Styles {
  [x: string]: CSS.Properties<JssValue<P>> | Styles<K, P>;
}
export type Styles<K extends string = any, P extends object = {}> = {
  [x in K]: CSS.Properties<JssValue<P>> | StylesObject<any, P> | StylesFn<P>
};

정상적으로 동작하지만, 타이프 스크립트가 에러를 쓴다. 용 i i i i를 쓴다.@ts-ignore 않다.

ERROR 24:11  typecheck  Interface 'StylesObject<K, P>' incorrectly extends interface 'Styles<any, {}>'.
  Index signatures are incompatible.
    Type 'Properties<JssValue<P>> | Styles<K, P>' is not assignable to type 'StylesFn<{}> | Properties<JssValue<{}>> | StylesObject<any, {}>'.
      Type 'Properties<JssValue<P>>' is not assignable to type 'StylesFn<{}> | Properties<JssValue<{}>> | StylesObject<any, {}>'.
        Type 'Properties<JssValue<P>>' is not assignable to type 'Properties<JssValue<{}>>'.
          Type 'JssValue<P>' is not assignable to type 'JssValue<{}>'.
            Type 'StylesFn<P>' is not assignable to type 'JssValue<{}>'.
              Type 'StylesFn<P>' is not assignable to type 'StylesFn<{}>'.
                Type '{}' is not assignable to type 'P'.
                  '{}' is assignable to the constraint of type 'P', but 'P' could be instantiated with a different subtype of constraint 'object'.

이 오류는 무엇을 의미합니까?

@fetz great answer를 보완합니다.


단답

TLDR: 이런 종류의 오류 메시지에는 두 가지 일반적인 원인이 있습니다.첫 번째 작업을 수행 중입니다(아래 참조).텍스트와 함께 이 에러 메시지가 무엇을 전하고 싶은지 자세히 설명합니다.

원인 1: 타이프스크립트에서는 구체적인 인스턴스를 타입 파라미터에 할당할 수 없습니다.'문제'와 '해결된 문제'의 예를 볼 수 있으므로 차이를 비교하고 어떤 변화가 있는지 확인할 수 있습니다.

문제

const func1 = <A extends string>(a: A = 'foo') => `hello!` // Error!

const func2 = <A extends string>(a: A) => {
    //stuff
    a = `foo`  // Error!
    //stuff
}

솔루션

const func1 = <A extends string>(a: A) => `hello!` // ok

const func2 = <A extends string>(a: A) => { //ok
    //stuff
    //stuff
}

참고 항목: TS Playground

원인 2: 코드에서 다음 오류가 발생하지 않습니다.이러한 에러 메세지가 표시되는 것도 정상적인 상황입니다.이 작업은 피해야 합니다.

Type Parameter클래스, 타입 또는 인터페이스로 지정합니다.

아래 코드의 복잡성으로 인해 혼란스러워하지 않도록 주의해 주시기 바랍니다.단, 알파벳 'A'를 제거하면 문제가 어떻게 해결되는지에만 집중해 주시기 바랍니다.

문제:

type Foo<A> = {
    //look the above 'A' is conflicting with the below 'A'
    map: <A,B>(f: (_: A) => B) => Foo<B>
}

const makeFoo = <A>(a: A): Foo<A> => ({
   map: f => makeFoo(f(a)) //error!
})

해결책:

type Foo<A> = {
    // conflict removed
    map: <B>(f: (_: A) => B) => Foo<B>
}

const makeFoo = <A>(a: A): Foo<A> => ({
   map: f => makeFoo(f(a)) //ok
})

참고 항목: TS Playground


장황한 답변


에러 메시지에 대해서

아래 오류 메시지의 각 요소를 분해합니다.

Type '{}' is not assignable to type 'P'.
  '{}' is assignable to the constraint of type 'P', but 'P' could be
 instantiated with a different subtype of constraint'object'

{}

null 또는 정의되지 않은 것을 제외한 모든 것을 할당할 수 있는 유형입니다.예를 들어 다음과 같습니다.

type A = {}
const a0: A = undefined // error
const a1: A = null // error
const a2: A = 2 // ok
const a3: A = 'hello world' //ok
const a4: A = { foo: 'bar' } //ok
// and so on...

참고 항목: TS Playground


★★에 is not assignable

할당이란 특정 유형의 변수를 특정 인스턴스에 대응시키는 것입니다.인스턴스 유형이 일치하지 않으면 오류가 발생합니다.예를 들어 다음과 같습니다.

// type string is not assignable to type number 
const a: number = 'hello world' //error

// type number is assinable to type number
const b: number = 2 // ok


different subtype

가지 유형은 동일합니다. 즉, 서로 관련된 세부 정보를 추가하거나 삭제하지 않는 경우입니다.

가지 유형이 다릅니다. 동일하지 않은 경우입니다.

Type은 type의 하위 유형입니다.A기존 상세정보를 삭제하지 않고 상세정보를 추가합니다.S.

type과 type은 type의 서브타입이 다릅니다.A ★★★★★★★★★★★★★★★★★」B는 의 입니다.SA ★★★★★★★★★★★★★★★★★」B른른른타타타다다 다음과 같습니다.A ★★★★★★★★★★★★★★★★★」B에 의해 됩니다.S, 같은 상세 내용을 추가하지는 않습니다.

예:다음 코드에서는 다음 문장이 모두 참입니다.

  1. A와 D는 동일한 유형입니다.
  2. B는 A의 서브타입이다.
  3. E는 A의 서브타입이 아닙니다.
  4. B와 C는 A의 다른 서브타입이다.
type A = { readonly 0: '0'}
type B = { readonly 0: '0', readonly foo: 'foo'}
type C = { readonly 0: '0', readonly bar: 'bar'}
type D = { readonly 0: '0'}
type E = { readonly 1: '1', readonly bar: 'bar'}
type A = number
type B = 2
type C = 7
type D = number
type E = `hello world`
type A = boolean
type B = true
type C = false
type D = boolean
type E = number

메모: 구조 유형

에서 TS의 되었을 때type " " " 입니다.type A = { foo: 'Bar' }다음을 읽어보십시오.type alias는 type structure를 가리키고 있습니다.

은 다음과 같습니다.type [type_alias_name] = [type_structure].

할 수 것은, 「Typescript type 」입니다.[type_structure] and and and and and and and and and and and and[type_alias_name], TS에서는 . 、 TS 서 、 TS 서 서 、 TS 음 에 、 TS 음 、 TS 음 . 。type A = { foo: 'bar } ★★★★★★★★★★★★★★★★★」type B = { foo: 'bar' }자세한 내용은 공식 문서를 참조하십시오.


★★에 constraint of type

Type Constraint는 단순히 'extends' 키워드의 오른쪽에 붙이는 것입니다.다음 예에서는Type Constraint입니다.비아냥거리다.

const func = <A extends B>(a: A) => `hello!`

확인: 유형 제약 조건 'B'는


에러가 발생하는 이유

예를 들면 세 가지 케이스를 보여드릴게요.은, 「이것」입니다.Type Constraint 않습니다

은, 「 」의 은, 「 」입니다.Type ConstraintType Parameter 에는 다른 서브타입은 포함되지 않습니다.어디 보자:

지정:

type Foo         =  { readonly 0: '0'}
type SubType     =  { readonly 0: '0', readonly a: 'a'}
type DiffSubType =  { readonly 0: '0', readonly b: 'b'}

const foo:             Foo         = { 0: '0'}
const foo_SubType:     SubType     = { 0: '0', a: 'a' }
const foo_DiffSubType: DiffSubType = { 0: '0', b: 'b' }

케이스 1: 제한 없음

const func = <A>(a: A) => `hello!`

// call examples
const c0 = func(undefined) // ok
const c1 = func(null) // ok
const c2 = func(() => undefined) // ok
const c3 = func(10) // ok
const c4 = func(`hi`) // ok
const c5 = func({}) //ok
const c6 = func(foo) // ok
const c7 = func(foo_SubType) //ok
const c8 = func(foo_DiffSubType) //ok

케이스 2: 몇 가지 제약 사항

아래에서는 제한은 하위 유형에 영향을 주지 않습니다.

매우 중요: 타이프 스크립트로Type Constraint 하지 않습니다.

const func = <A extends Foo>(a: A) => `hello!`

// call examples
const c0 = func(undefined) // error
const c1 = func(null) // error
const c2 = func(() => undefined) // error
const c3 = func(10) // error
const c4 = func(`hi`) // error
const c5 = func({}) // error
const c6 = func(foo) // ok
const c7 = func(foo_SubType) // ok  <-- Allowed
const c8 = func(foo_DiffSubType) // ok <-- Allowed

케이스 3: 제약 강화

const func = <A extends SubType>(a: A) => `hello!`

// call examples
const c0 = func(undefined) // error
const c1 = func(null) // error
const c2 = func(() => undefined) // error
const c3 = func(10) // error
const c4 = func(`hi`) // error
const c5 = func({}) // error
const c6 = func(foo) // error <-- Restricted now
const c7 = func(foo_SubType) // ok  <-- Still allowed
const c8 = func(foo_DiffSubType) // error <-- NO MORE ALLOWED !

TS 플레이그라운드를 참조해 주세요.


결론

아래 함수는 다음과 같습니다.

const func = <A extends Foo>(a: A = foo_SubType) => `hello!` //error!

다음 오류 메시지가 나타납니다.

Type 'SubType' is not assignable to type 'A'.
  'SubType' is assignable to the constraint of type 'A', but 'A'
could be instantiated with a different subtype of constraint 
'Foo'.ts(2322)

는 "Typescript"를하기 때문입니다.AFoo'의 다른 서브타입으로 함수를 호출하는 것을 제한하는 언어에는 제한이 없습니다.예를 들어, 아래의 모든 함수의 호출은 유효한 것으로 간주됩니다.

const c0 = func(foo)  // ok! type 'Foo' will be infered and assigned to 'A'
const c1 = func(foo_SubType) // ok! type 'SubType' will be infered
const c2 = func(foo_DiffSubType) // ok! type 'DiffSubType' will be infered

합니다.Type Parameter에서는 이 틀렸기 때문입니다.TSType Parameter는 항상 임의의 다른 서브타입으로 인스턴스화할 수 있습니다.

솔루션:

파라미터에 이는 「알겠습니다」라고 해 주세요.read-only신신음 음

const func = <A extends Foo>(a: A) => `hello!` //ok!

TS Playground 참조

Type을 입니다. 범용 타입 †P이 안 되다{} Type ]그래서 [Generic Type]이래P는 디폴트값과 경합할 가능성이 있는 특정 타입으로 정의 또는 제한할 수 있습니다.

, 값 「」, 「」가{} Type Generic Type에서 할 수 수 .P.

이해하기 쉬운 부울만 사용하여 다른 예를 만들어 보겠습니다.

interface OnlyBoolIdentityInterface<T extends boolean> {
  (arg: T): T;
}

function onlyBoolGeneric<T extends boolean>(arg: T = false): T {
  return arg;
}

예를 들어 부울보다 구체적인 유형을 정의하는 경우:

type TrueType = true;

그리고 만약 당신이 그 기능을 전문화했다면OnlyBoolIdentityInterface하다

const onlyTrueIdentity: OnlyBoolIdentityInterface<TrueType> = onlyBoolGeneric;

이 TrueType에 의해 T extends boolean '''arg: T = false 아니다TrueType.

이것이 에러가 전달하려고 하는 상황입니다.

그러면 이런 유형의 오류를 어떻게 해결할 수 있을까요?

  1. 또는 기본값을 삭제합니다.
  2. 또는 T는 디폴트파라미터의 특수한 유형을 확장해야 합니다.이 예에서는 false입니다.
  3. 또는 T가 디폴트 파라미터를 수신하는 파라미터에 직접 간섭할 수 있습니다.

이 오류 메시지에 대한 자세한 내용은 이 오류 메시지를 제시한 문제를 참조하십시오.https://github.com/Microsoft/TypeScript/issues/29049

조금 더 간략하게 설명하겠습니다.

에러를 발생시키는 예:

type ObjectWithPropType<T> = {prop: T};

// Mind return type - T
const createCustomObject = <T extends ObjectWithPropType<any>>(prop: any): T => ({ prop });

type CustomObj = ObjectWithProp<string> & { id: string };

const customObj = createCustomObj<CustomObj>('value'); // Invalid
// function will only ever return {prop: T} type.

객체가 항상 인 "Atribute"에만입니다.prop다른 속성은 없습니다.의 확장ObjectWithPropType잘못된 유형의 제약이 있음을 나타냅니다.이 예에서는 오브젝트 속성의 실제 경합을 나타내기 위해 단순히 그림으로 사용한 잘못된 접근법입니다.

작성 함수에서 하위 유형을 제한하는 방법:

type StringPropObject = ObjectWithPropType<string>

const createCustomObject = <T>(prop: T extends ObjectWithPropType<infer U> ? U : T): ObjectWithPropType<T> => ({ prop });

const stringObj = createCustomObject<StringPropObject>('test');

이 경우 함수는 인수를 문자열로 해야 합니다.에는 「」만 .prop속성 및 함수가 필요한 쉐이프를 반환합니다.

@flavio-vilante의 훌륭한 답변을 보완합니다.

그래도 필요한 경우(인수는 생략할 수 있으며 생략할 경우 폴백합니다).

const func = <A extends Foo>(a: A = foo_SubType) => `hello!` //error!

시험 가능:

const func = <A extends Foo>(a?: A) => {
    const aa = a === undefined ? foo_SubType : a;
    return `hello!`;
} 

않고 .Foo대신 직접.

const func = (a: Foo = foo_SubType) => `hello!`

내 경우 일반 유형의 열거형(T extenses enum)을 사용하여 다음과 같은 컴포넌트를 선택하고 싶었다.

export function BasicSelector<T extends string>(props: IProps<T>) {

그리고 "Type 'string' is not assignable to type 'T'" 라는 에러가 발생했습니다.그래서 결국 Type을 적용했습니다.

          onChange={(e) => onChange(e.target.value as T)}

언급URL : https://stackoverflow.com/questions/56505560/how-to-fix-ts2322-could-be-instantiated-with-a-different-subtype-of-constraint

반응형