指定参数类型为T |空但非空

时间:2018-07-27 20:37:37

标签: typescript null

我编写了一个函数,该函数可以处理传递的是null或未定义的值而不是T,在这种情况下什么也不做,并返回一些默认值。

但是,在许多情况下,编译器很聪明,可以在编译期间知道传入的值不是T或null,而是100%的时间为null,我希望在其中出现编译器错误情况。

示例:

<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/fragment"
    android:name=".fragments.DataFragment"
    tools:layout="@layout/data_fragment"/>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".activities.MainActivity"
   />

在这种情况下,开发人员不想将null传递给函数并依赖于其默认值,而是使用其他值,但是开发人员混淆了if语句的分支。编译器足够聪明,可以知道obj为null,但是确定的null与null一样有效。

可以做到吗?我正在使用打字稿2.9.2版。可以升级到3。

ps。我在类型系统中寻找解决方案,而不是用“也许单子”对象代替“ T | T”。空值”。

2 个答案:

答案 0 :(得分:2)

一定要爱类型的黑客...

const functionThatTakeTheUnionType = <T>(p: T & ([T] extends [null] ? never : T)) => {
    // ...
}

参数类型中的第一个T使推理工作。然后,如果在编译时推断T肯定是null,则我们与never的类型相交,这肯定会导致错误。如果推断T类似于MyObject | null,我们将再次与T相交,这没有任何效果;请注意,由于T | null已经包含T(如果适用),因此不必写null

答案 1 :(得分:0)

您可以使用重载函数声明,当编译器明确知道参数为null时,该声明将返回不适当的内容,例如void

function functionThatTakeTheUnionType(p: null): void;
function functionThatTakeTheUnionType<T extends { name: string }>(p: T | null): string;
function functionThatTakeTheUnionType<T extends { name: string }>(p: T | null): string {
    return p && typeof p.name === 'string' ? p.name : 'default';
}

declare function functionReturningTOrNull(): { name: string } | null;

function a() {
    let obj = functionReturningTOrNull();
    let name: string;
    if (obj === null) {
        // error: Type 'void' is not assignable to type 'string'.
        name = functionThatTakeTheUnionType(obj)
    } else {
        name = 'different default name';
    }

    let obj2 = functionReturningTOrNull();
    let name2 = functionThatTakeTheUnionType(obj2); // string
}

但这仅在functionThatTakeTheUnionType被声明为function而不是具有功能值的对象的情况下有效。

此外,仅当有人使用functionThatTakeTheUnionType的结果时,它才会给出错误-我不知道是否有任何方法可以使编译器对其参数产生错误。