Ram*_*ran 9 variables types typescript typescript-typings angular
以下这些方案是接受和不可接受的声明.
export class MyComponent{
error: 'test' = 'test'; // accept
error: 'test' = 'test1'; // not accept
error: Boolean = true || false; // accept
error: true | false = true; // not accept
error: true = true; // accept
error: true = false; // not accept
error: Boolean; //accept
error: true; // accept
error: 1 = 1; //accept
error: 1 = 2; // not accept
}
Run Code Online (Sandbox Code Playgroud)
- 为什么TypeScript允许将值作为数据类型?
- JavaScript如何在编译时处理这些?
- 它
readonly
和constant
?有什么不同?
readonly error= 'test';
与 error: 'test' = 'test';
Alu*_*dad 10
首先,一些非正式的背景和信息将帮助我们讨论您提出的问题:
通常,类型表示一组0或更多值.这些价值观可以被视为该类型的成员或居民.
就它们可以采用的这种多样性而言,类型往往落在3组中的1组中.
第1组:例证:string
类型.该string
类型由所有字符串值居住.由于字符串可以有效地任意长,因此基本上存在作为该string
类型的成员的无限数值.作为此类型成员的值集是所有可能字符串的集合.
第2组:例证:undefined
类型.该undefined
类型只有一个值,即undefined
值.因此,此类型通常称为单例类型,因为其成员集只有1个值.
第3组:例证:never
类型.该never
类型没有成员.根据定义,不可能具有类型的值never
.当你在专业人士中阅读它时,这看起来有点令人困惑,但是一个小代码示例可以解释它.
考虑:
function getValue(): never {
throw Error();
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,函数getValue
具有返回类型,never
因为它永远不会返回值,它总是抛出.因此,如果我们写
const value = getValue();
Run Code Online (Sandbox Code Playgroud)
value
也将是类型never
.
现在回答第一个问题:
为什么打字稿允许值作为数据类型?
有许多原因,但有一些特别引人注目的原因
根据传递给它们的值来模拟行为不同的函数的行为.想到的一个例子是功能document.getElementsByTagName
.此函数始终采用type的值string
,并始终返回NodeList
包含HTMLElement
s的值.但是,根据传递的实际字符串值,它将返回该列表中完全不同类型的事物.这些元素之间唯一的共同点是它们都来源于HTMLElement
.
现在,让我们考虑一下如何写下这个函数的类型签名.我们的第一次尝试可能是这样的
declare function getElementsByTagName(tagname: string): NodeList<HTMLElement>;
Run Code Online (Sandbox Code Playgroud)
这是正确的,但它并不是特别有用.想象一下,我们想要获取页面上所有HTMLInput元素的值,以便我们将它们发送到我们的服务器.
我们知道getElementsByTagName('input')
,实际上只返回页面上的输入元素,正是我们想要的,但是通过上面的定义,当我们获得正确的值(TypeScript不会影响JavaScript运行时行为)时,它们将具有错误的类型.具体来说,它们是类型HTMLElement
,超类型HTMLInputElement
没有value
我们想要访问的属性.
所以,我们能做些什么?我们可以"转换"所有返回的元素,HTMLInputElement
但这很丑陋,容易出错(我们必须记住所有的类型名称以及它们如何映射到它们的标记名称),冗长和一点点钝,我们知道的更好,我们静态地了解.
因此,变得需要将之间的关系进行建模值的tagname
,这是参数getElementsByTagName
,它实际上返回元件的类型.
输入字符串文字类型:
字符串文字类型是一种更精炼的字符串类型,它是单例类型,就像undefined
它只有一个值一样,即文字字符串.一旦我们有这种类型的,我们能够超载的声明getElementsByTagName
使得它优越准确和有用
declare function getElementsByTagName(tagname: 'input'): NodeList<HTMLInputElement>;
declare function getElementsByTagName(tagname: string): NodeList<HTMLElement>;
Run Code Online (Sandbox Code Playgroud)
我认为这清楚地证明了具有专门的字符串类型的效用,这些字符串类型是从一个值派生的,并且只有该单个值所居住,但是还有很多其他原因可以使用它们,所以我将再讨论一些.
在前面的例子中,我会说易用性是主要动机,但请记住,TypeScript的#1目标是通过编译时,静态分析来捕获编程错误.
鉴于此,另一个动机是精确性.有许多JavaScript API具有特定的价值,并且取决于它是什么,它们可以做一些非常不同的事情,什么都不做,或者很难.
因此,对于另一个真实示例,SystemJS是一个优秀且广泛使用的模块加载器,具有广泛的配置API.您可以传递给它的一个选项被调用,transpiler
并且根据您指定的值,将发生非平凡的不同事情,此外,如果您指定了无效值,它将尝试加载不存在的模块并失败加载其他任何东西.对于有效值transpiler
是:"plugin-traceur"
,"plugin-babel"
,"plugin-typescript"
,和false
.我们不仅希望TypeScript能够提供这4种可能性,还要检查我们是否仅使用其中一种可能性.
在我们将离散值用作类型之前,此API很难建模.
充其量,我们必须写类似的东西
transpiler: string | boolean;
Run Code Online (Sandbox Code Playgroud)
这不是我们想要的,因为只有3个有效字符串且true
不是有效值!
通过将值用作类型,我们实际上可以完美地描述此API
transpiler: 'plugin-traceur' | 'plugin-babel' | 'plugin-typescript' | false;
Run Code Online (Sandbox Code Playgroud)
并且不仅知道我们可以通过哪些值,而且如果我们错误地键入'plugin-tsc'
或尝试通过则立即得到错误true
.
因此,字面类型可以及早捕获错误,同时实现Wilds中现有API的精确描述.
另一个好处是控制流分析,它允许编译器检测常见的逻辑错误.这是一个复杂的主题,但这是一个简单的例子:
declare const compass: {
direction: 'N' | 'E' | 'S' | 'W'
};
const direction = compass.direction;
// direction is 'N' | 'E' | 'S' | 'W'
if (direction === 'N') {
console.log('north');
} // direction is 'E' | 'S' | 'W'
else if (direction === 'S') {
console.log('south');
} // direction is 'E' | 'W'
else if (direction === 'N') { // ERROR!
console.log('Northerly');
}
Run Code Online (Sandbox Code Playgroud)
上面的代码包含一个相对简单的逻辑错误,但是由于复杂的条件和各种人为因素,在实践中很容易错过.第三个if
基本上是死代码,它的主体永远不会被执行.文字类型允许我们将可能的指南针声明direction
为"N","S","E"或"W"之一的特殊性使编译器能够立即将第三个if语句标记为无法访问,实际上是无意义的代码,表示我们程序中的错误,一个逻辑错误(毕竟我们只是人类).
因此,我们还有一个主要的激励因素,能够定义与可能值的非常特定的子集相对应的类型.最后一个例子中最好的部分就是我们自己的代码.我们想要宣布一个合理但非常具体的合同,这种语言为我们提供了表达能力,然后在我们违反合同时抓住了我们.
以及Javascript如何在编译时处理它们?
与所有其他TypeScript类型完全相同.它们完全从TypeScript编译器发出的JavaScript中删除.
它与readonly和constant有何不同?
与所有TypeScript类型一样,您所说的类型,指示特定值的类型,与const
和readonly
修饰符交互.这种相互作用有点复杂,可以浅谈,就像我在这里做的那样,或者很容易构成一个Q/A.
可以这么说,const
并且readonly
对可能的值有影响,因此对变量或属性在任何时候实际可以容纳的可能类型都有影响,因此使得文字类型,特定值类型的类型,更容易传播,推理,也许最重要的是推断我们.
因此,当某些东西是不可变的时,通常有必要推断它的类型尽可能具体,因为它的价值不会改变.
const x = 'a';
Run Code Online (Sandbox Code Playgroud)
推断的类型x
是'a'
因为它不能被重新分配.
let x = 'a';
Run Code Online (Sandbox Code Playgroud)
另一方面,推断的类型x
是string
因为它是可变的.
现在你可以写
let x: 'a' = 'a';
Run Code Online (Sandbox Code Playgroud)
在这种情况下,虽然它是可变的,但只能赋予类型的值'a'
.
请注意,对于说明目的而言,这有点过于简单化了.
在if else if
上面的例子中可以观察到有其他机制在工作,这表明该语言有另一层,控制流分析层,它跟踪可能的值类型,因为它们通过条件,赋值,真值检查缩小,和其他构造如解构赋值.
现在让我们详细检查您的问题中的类,属性属性:
export class MyComponent {
// OK because we have said `error` is of type 'test',
// the singleton string type whose values must be members of the set {'test'}
error: 'test' = 'test';
// NOT OK because we have said `error` is of type 'test',
// the singleton string type whose values must be members of the set {'test'}
// 'test1' is not a member of the set {'test'}
error: 'test' = 'test1';
// OK but a word of Warning:
// this is valid because of a subtle aspect of structural subtyping,
// another topic but it is an error in your program as the type `Boolean` with a
// capital "B" is the wrong type to use
// you definitely want to use 'boolean' with a lowercase "b" instead.
error: Boolean = true || false;
// This one is OK, it must be a typo in your question because we have said that
// `error` is of type true | false the type whose values must
// be members of the set {true, false} and true satisfies that and so is accepted
error: true | false = true;
// OK for the same reason as the first property, error: 'test' = 'test';
error: true = true;
// NOT OK because we have said that error is of type `true` the type whose values
// must be members of the set {true}
// false is not in that set and therefore this is an error.
error: true = false;
// OK this is just a type declaration, no value is provided, but
// as noted above, this is the WRONG type to use.
// please use boolean with a lowercase "b".
error: Boolean;
// As above, this is just a type, no value to conflict with
error: true;
// OK because we have said `error` is of type 1 (yes the number 1),
// the singleton number type whose values must be members of the set {1}
// 1 is a member of {1} so we are good to go
error: 1 = 1;
// NOT OK because we have said `error` is of type 1 (yes the number 1),
// the singleton number type whose values must be members of the set {1}
// 2 is NOT a member of {1} so this is an error.
error: 1 = 2;
}
Run Code Online (Sandbox Code Playgroud)
TypeScript与类型推理有关,推理越多越好,因为它能够传播来自值的类型信息,例如表达式,并使用它来推断更精确的类型.
在大多数语言中,类型系统以类型开始,但在TypeScript中,这种情况几乎总是如此,类型系统以值开头.所有值都有类型.对这些值的操作会产生新值,新类型允许类型干扰进一步传播到程序中.
如果将纯JavaScript程序粘贴到TypeScript文件中,您会注意到,如果不添加任何类型的注释,它就能够找到很多关于程序结构的信息.文字类型进一步增强了这种能力.
关于文字类型还有很多可以说的,为了解释的目的,我已经省略并简化了某些事情,但请放心,它们很棒.
归档时间: |
|
查看次数: |
868 次 |
最近记录: |