一行代码引发的离奇问题,众多大佬纷纷参与点评,最终Typescript之父出手解决

故事的起因是这样的, 一个前端开发人员(也算是挺有名的,ariakit.org的作者, wrodPress的前维护者)在社交媒体上发了这么一条帖子。

一行代码引发的离奇问题,众多大佬纷纷参与点评,最终Typescript之父出手解决

短短几天就有了51.8万次的view。 简单的文案:又是使用 TypeScript 的一天.。表达了对Typescript的又爱又恨😂。在目前的前端市场上,Typescript已经成为标配,ts强大的类型检查机制给我们带来了非常多的好处(代码质量,强大的可维护性,代码即注释),但是其槽点也很多, 很多奇奇怪怪的问题(相信不仅是我一个人这么觉得),繁多的配置项组合,稍不注意就会引起页面爆红,代码量增多和代码组织也会引起一定的负担。但在这些并不能撼动Typescript 在目前前端社区中的地位,在开发项目中一般还是会选择typescript。

反应

话说回到这个帖子上,这个帖子发出来之后迅速引起发酵,被很多大佬转发和引用,下面的评论很多都是wait, what, why happen?类似的语气😂,有很多给出建议,比如换种写法, 重启下Typescript server试试,也有很多开发爱好者希望作者能提供一个例子来复现,他们也想看看是什么问题,看能不能尝试解决这个有趣的例子。

(ps: 在ts中有很多奇怪的东西,特别是在和编辑器配合的时候,有些时候不能判断出来是否是个bug?还是我们代码写的有问题?还是设计如此?还是编辑器的问题?还是版本兼容问题?仅代表个人看法)

复现例子

后来有大佬根据作者提供的信息复现出来了样板例子

declare function hasOwnProperty<T extends AnyObject>(
  object: T,
  prop: keyof any,
): prop is keyof T;

type EffectCallback = () => void;

declare const useSafeLayoutEffect: (effect: EffectCallback) => void;

type AnyObject = Record<string, any>;
export type State = AnyObject;

type AnyFunction = (...args: any) => any;
type BivariantCallback<T extends AnyFunction> = {
  bivarianceHack(...args: Parameters<T>): ReturnType<T>;
}["bivarianceHack"];
type SetStateAction<T> = T | BivariantCallback<(prevState: T) => T>;

interface Store<S = State> {
  getState(): S;
  setState<K extends keyof S>(key: K, value: SetStateAction<S[K]>): void;
}

export function useStoreProps<
  S extends State,
  P extends Partial<S>,
  K extends keyof S,
>(store: Store<S>, props: P, key: K) {
  const value = hasOwnProperty(props, key) ? props[key] : undefined;

  useSafeLayoutEffect(() => {
    if (value === undefined) return;
    value;
    // ^?
    if (value === undefined) return; // toggle this to see the magic
    value;
    // ^?
    store.setState(key, value);
  });
}

将鼠标放到倒数第八行上显示value的类型:

const value: P[K] & ({} | null)

但是将鼠标放到倒数第五行时显示的value类型:

const value: P[K] & {}

真是见了鬼了。同样的操作复制了一遍,显示的类型却不一样?是的,这很Typescript😏。

提出issue

issue的地址在这

一行代码引发的离奇问题,众多大佬纷纷参与点评,最终Typescript之父出手解决

这个提出issue的哥们就是复现样板例子的人,看的出来他应该是个狂热的技术爱好者,执行力也很强,从问作者要出现这种情况的代码仓库可以是否可以公开 ==> 复现样板例子 ==> 给Typescript提出issue(还尝试了自己能不能解决),执行力power👍。

Typescript之父出手解决

在提出issue之后立即就被官方定位是一个bug, 而且Typescript之父还给出了一个简化版可复现的例子:

function f1<T extends Record<string, any>, K extends keyof T>(x: T[K] | undefined) {
    if (x === undefined) return;
    x;  // T[K] & ({} | null)
    if (x === undefined) return;
    x;  // T[K] & {}
}

通过上面的例子发现null被意外的消除了。

ahejlsberg(ts之父) 写了一个规范化nullundefined在类型系统中的表现的函数解决了这个问题。

一行代码引发的离奇问题,众多大佬纷纷参与点评,最终Typescript之父出手解决

至此issue被关闭。

我们打开palyground的nightly版本,可以发现这个问题被解决, 错误不在显示了。

总结

这是无意间从网上看到,然后从问题追溯到问题被一步步的解决。从帖子中可以看出来现在大部分用Typescript写项目的人又爱又恨的普遍状态。不管你是多菜的菜鸟也能感受到ts给日益庞大的前端项目带来的好处,不管你是多厉害的大牛也是会遇到一些奇怪的错误。随着Typescript的普及,社区中有很多不同的声音,有热爱者,有反对者,也有随波逐流者,但这也代表Typescript在社区中展现的旺盛生命力。质疑也好,热爱也罢,我觉得ts会越来越好。

往期文章

原文链接:https://juejin.cn/post/7347210988260147210 作者:xinling_any

(0)
上一篇 2024年3月18日 下午4:28
下一篇 2024年3月18日 下午4:39

相关推荐

发表回复

登录后才能评论