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

typescript - Assign a value to a generic constraint that extends a primitive type - Stack Overflow

programmeradmin3浏览0评论

I have the following function

function fun<T extends boolean>(param: T): void {
    param = true
}

When I assign param to true, the compiler gives me the following error:

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

Why can't I assign it? T is (or at least extends) boolean, so it should work.

There is a workaround to add <T> before true or as T after true, but that's just annoying to do all the time.

It's also more annoying when you try to add a default value to param:

function fun<T extends boolean>(param: T = true): void

Now there is an error on param: T = true which is the same exact one as the previous error.

Why can't I just assign to param without explicitly type-asserting (adding <T> or as T) the value?

I have the following function

function fun<T extends boolean>(param: T): void {
    param = true
}

When I assign param to true, the compiler gives me the following error:

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

Why can't I assign it? T is (or at least extends) boolean, so it should work.

There is a workaround to add <T> before true or as T after true, but that's just annoying to do all the time.

It's also more annoying when you try to add a default value to param:

function fun<T extends boolean>(param: T = true): void

Now there is an error on param: T = true which is the same exact one as the previous error.

Why can't I just assign to param without explicitly type-asserting (adding <T> or as T) the value?

Share Improve this question edited Feb 16 at 10:34 jonrsharpe 122k30 gold badges267 silver badges474 bronze badges asked Feb 16 at 9:57 Space.ygSpace.yg 551 silver badge5 bronze badges 1
  • It's because nothing stops you from calling fun<false>(), and then you've assigned true to false. You're presumably looking for ms/TS#58977 and since that feature doesn't exist, there are only workarounds, none of which are perfect. You can use true as T and just assume nobody will explicitly instantiate false as the type argument, or use overloads. Does this fully address the question? If so I'll write an answer or find a duplicate. If not, what's missing? – jcalz Commented Feb 16 at 14:28
Add a comment  | 

1 Answer 1

Reset to default 1

Basically, just because you have two different sub types does not mean you can assign one to other.

true and false are subtypes, but if a value explicitly expects the value false, you cannot assign true right.

It is a little difficult to find practical examples with primitives, but with objects it does make a lot of sense. And, in JS anything can be an object :D.


I hope the below snippet is helpful. Here we have both kinds of example. Please check the comments too:

function fun<T extends boolean>(param: T): void {
    param = true //The error
}

const val: false = false; //val can only be false

type PrimitiveWithRandomFunc = false & { func? : () => void };

type ExtendsWrong = PrimitiveWithRandomFunc extends boolean ? true : false;

let m :false & { func? : () => void }  = false; //m can only be false and have a func in addition

m.func = () => {
  console.log("yolo");
} 

fun(val) //no error, although we are assigning true to val, which should be false

fun(m) //no error
 

If one is to create a type like PrimitiveWithRandomFunc, which is possible in JavaScipt, then the above error makes sense.

ExtendsWrong is true type, which means the extension constraint is match. But just because it is matched does not mean that we can assign a different subtype to param.

Notice how fun(m) does not give any error. I am using func as optional property to get rid of some TS errors, but I hope it gets the point across. Basically you would be assigning true to something that only expects fale and some other things.

And for val I hope it is clearly apparent, we are simply able to assign true to something that should be false.

Playground

发布评论

评论列表(0)

  1. 暂无评论