输入非假,也就是真

Posted

技术标签:

【中文标题】输入非假,也就是真【英文标题】:Type for non-false, aka truthy 【发布时间】:2018-12-25 16:20:15 【问题描述】:

在 TypeScript 中,有truthy 的类型吗?

我有这个方法: Object.keys(lck.lockholders).length; 入队(k:任何,obj?:任何):无效 顺便说一下,使用 TS 有一种方法可以检查空字符串 ''。 我想将其转换为:

  enqueue(k: Truthy, obj?: any): void

除了我不知道如何定义 Truthy 的类型。顺便说一句,我认为 TS 有一种方法可以检查空字符串 ''。

我想要这个的原因是我不希望用户将nullundefined'' 等作为哈希的键。

【问题讨论】:

注意string 不能转换成这样的类型(因为'' 是假的,但是是string),限制了它的用处。 这似乎是您想要在运行时检查的内容。 Truthy 类型感觉有点超出 TS 的范围 【参考方案1】:

我不确定你为什么需要这个,但它很有趣。老实说,简短的回答是:TypeScript 不适用于此,您最好进行运行时检查并记录您的代码,以便开发人员知道k 参数应该是真实的。不过,如果您打算强制 TypeScript 执行此类操作,请继续阅读:


注意:要使以下内容正常工作,请打开strictNullChecks 编译器选项。这是有必要的,因为无法区分 TruthyTruthy | null | undefined 将是一个问题。

你可以几乎定义falsy,就像

type Falsy = false | 0 | "" | null | undefined 

除了NaN 也是假的,TypeScript 没有NaN 的数字文字(请参阅microsoft/TypeScript#15135)。

即使您有上述Falsy,TypeScript 中也没有否定类型(请参阅microsoft/TypeScript#4196),因此无法将Truthy 表示为“除了Falsy 之外的所有内容”。

您可以尝试使用conditional types 来排除enqueue() 中可能存在错误的参数,但这很奇怪:

type DefinitelyTruthy<T> =
  false extends T ? never :
  0 extends T ? never :
  "" extends T ? never :
  null extends T ? never :
  undefined extends T ? never :
  T

declare function enqueue<T extends number | string | true | object>(
  k: T & DefinitelyTruthy<T>,
  obj?: any
): void

declare const str: string;
enqueue(str); // error, might be falsy
enqueue("a"); // okay
enqueue(1); // okay
enqueue(0); // error
enqueue(NaN); // error
enqueue(true); // okay
enqueue(false); // error
enqueue([]); //okay
enqueue(a: "hello"); // okay
enqueue(); // error, interpreted as type  which could be an empty string:
const zilch = "" as ;
enqueue(zilch); // error, see? 

注意它不允许任何它认为可能是虚假的,这可能是你想要达到的目标。说不出来。


更新

我看到您编辑了问题以澄清k 参数实际上应该是string(或者可能是symbol),并且您需要排除的唯一值是空字符串""。在这种情况下,您可以将上述内容简化为:

type DefinitelyNotEmptyString<T> = "" extends T ? never : T

declare function enqueue<T extends string | symbol>(
  k: T & DefinitelyNotEmptyString<T>,
  obj?: any
): void

enqueue(""); // error
enqueue("a"); // okay

所有这一切都很好,但不幸的是,如果您将一般的 string 传递给 enqueue() 它将失败,有时开发人员可能需要这样做,如果他们用于 @987654347 的值@ 参数不是他们指定的字符串文字:

declare const str: string; // comes from somewhere else
enqueue(str); // error!  how do I do this?

为了解决这个问题,您可以尝试创建一个nominal type,您可以使用它来向编译器标识一个值已被检查为空,然后创建一个user-defined type guard 来约束一个string类型:

type NotEmptyString = string & "***NotEmptyString***": true;
function notEmptyString(x: string): x is NotEmptyString 
  return x !== "";

现在开发者可以这样做了:

declare const str: string;
enqueue(str); // error, might be falsy
if (notEmptyString(str)) 
  enqueue(str); // okay, str is NotEmptyString


哇!这是很多箍跳。如果您认为这是值得的,这取决于您。好的,希望有帮助。祝你好运!

【讨论】:

我在typescript playground 中尝试过这个,但它对所有内容都出错了。例如enqueue("a") 给出错误Argument of type '"a"' is not assignable to parameter of type 'never'. 打开--strictNullChecks...如果你想区分undefined/null和真实的东西,你可能需要它。【参考方案2】:

没有Truthy 类型,但是你可以利用类型保护系统 (type predicate) 来帮助 TypeScript 了解真正的 truthy 并分配它truthy 类型!

让我们定义Falsy类型和genericisTruthy函数:

type Falsy = false | 0 | '' | null | undefined;

// this is a type predicate - if x is `truthy`, then it's T
const isTruthy = <T>(x: T | Falsy): x is T => !!x;

现在我们可以使用 isTruthy 函数来查找 Truthy 值,TypeScript 会正确地将 "truthy" 类型分配给结果。

示例:

   // removing boolean "false" type
  const result: string | false = Math.random() > 0.5 ? 'a' : false;
  const truthyResult: string = isTruthy(result) ? result : 'was false';

   // filtering only numbers from array
  const result: (number | undefined)[] = [42, undefined, 8, 16];
  const truthyResult: number[] = result.filter(isTruthy);

   // filtering only Promises from array
  const result: (Promise<string> | null)[] = [Promise.resolve('a'), null, Promise.resolve('b'), Promise.resolve('c')];
  const truthyResult: Promise<string>[] = result.filter(isTruthy);


【讨论】:

请注意。 0 是一个数字(即使是错误的)。因此,第二个示例实际上会从数组中过滤掉 0,一个数字,如果它存在于数组中。 在看到你的评论之前我就是这样做的哈哈,对我来说足够好的解决方案

以上是关于输入非假,也就是真的主要内容,如果未能解决你的问题,请参考以下文章

python 运算符

字体真棒,输入类型“提交”

运算符 and or ont

APPium连接真机输入框中输入的内容与代码中不一致

物化输入内的字体真棒图标

python里面的数学