最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

reactjs - custom type with conditional generic type gives ts error when used in useState - Stack Overflow

programmeradmin7浏览0评论

I have a type definition like so:

export type MutationResponse<T = never> = {
    status: number;
    message: string | null;
} & (T extends never ? {} : { data: T });

When i use it like so:

const [response, setResponse] = useState<MutationResponse>({ status: 0, message: "" });

I get the following error:

Object literal may only specify known properties, and 'status' does not exist in type '() => never'

Why is this and how do i fix this?

fyi, when i use it with the generic type parameter specified like so it works just totally fine:

const [response, setResponse] = useState<MutationResponse<string>>({ status: 0, message: "", data: "" });

I have a type definition like so:

export type MutationResponse<T = never> = {
    status: number;
    message: string | null;
} & (T extends never ? {} : { data: T });

When i use it like so:

const [response, setResponse] = useState<MutationResponse>({ status: 0, message: "" });

I get the following error:

Object literal may only specify known properties, and 'status' does not exist in type '() => never'

Why is this and how do i fix this?

fyi, when i use it with the generic type parameter specified like so it works just totally fine:

const [response, setResponse] = useState<MutationResponse<string>>({ status: 0, message: "", data: "" });
Share Improve this question edited Mar 21 at 4:42 Drew Reese 204k18 gold badges245 silver badges273 bronze badges asked Mar 21 at 0:16 FutureCakeFutureCake 2,9653 gold badges33 silver badges77 bronze badges 0
Add a comment  | 

2 Answers 2

Reset to default 1

The issue is the below code segment.

...
& (T extends never ? {} : { data: T });

Please observe the below test types. While Type2 is never, Type4 is {}. The reason is given below.

type Type1<T> = T extends never ? {} : { data: T }

type Type2 = Type1<never>;  // never

type Type3<T> = [T] extends [never] ? {} : { data: T }

type Type4 = Type3<never>; // {}

Type1 is a distributive conditional type. Conditional types distribute over unions. never is the empty union (ie a union with no members). So when distributing over never, Type1 is never applied, since there are no members in this union and thus the result is never.

In Type3, the distribution behaviour is disabled. Therefore it produces the desired result.

Citation:

Generic conditional type T extends never ? 'yes' : 'no' resolves to never when T is never.

Honestly, I'm not the best person to explain why never is not working in your type. The never keyword is still a little hard to digest for me.

That being said, the problem isn't against the useState, but in the type usage itself. You won't able to create an object from that type:

type MutationResponse<T = never> = {
    status: number;
    message: string | null;
} & (T extends never ? {} : { data: T });

const mr_never: MutationResponse = {  //won't compile
    status: 123,
    message: "abc",
}

Thus, I suggest to turn the definition to void instead of never:

type MutationResponse2<T = void> = {
    status: number;
    message: string | null;
} & (T extends void ? {} : { data: T });

const mr_void: MutationResponse2 = {
    status: 123,
    message: "abc",
}

const mr_bool: MutationResponse2<boolean> = {
    status: 456,
    message: "def",
    data: true
}

That should be fine for your purposes.

I hope someone will give you a more detailed answer on the original problem, though.

发布评论

评论列表(0)

  1. 暂无评论