1.关于基础类型(重点说 any、object等)
any
刚开始的问题是 any 用的比较多,但是事实上,type-check 本来就是为了确定类型,写那么多不能确定类型的 any 干什么
适用于any的情况:
当我们确实不知道变量的类型的时候,需要取消类型检查。例如下面的情况(These values may come from dynamic content)
- from the user
- from a 3rd party library
- you know part of the type,but not all of it (Array)
1 | let list: any[] = [1, true, "free"]; |
any是一个非常有用的方式,对于 引入 还是取消类型检查。
与Object不同—调用方法
1 | let notSure: any = 4; |
object
非基础类型 使用object,i.e.
any thing that is not
number
,string
,boolean
,symbol
,null
, orundefined
.
1 | declare function create(o: object | null): void; |
Type assertions—
相当于强制类型转换
自己了解到的类型的信息比TS要多,你知道的额尸体类型的信息比现在要更具体的时候
两种方式写 Type assertions
value - value as type
举例:
1 | let someValue: any = "this is a string"; |
1 | let someValue: any = "this is a string"; |
2.interfaces(接口)
变量
注意点:
- 实际传入的可以比接口中定义的类型多,因为只是检查必须的
1 | interface LabelledValue { |
只是检查必须的
- 接口中的可选属性
- readonly 只能在声明时赋值,但是可以使用断言的方式
1 | let a: number[] = [1, 2, 3, 4]; |
- readonly与const
变量使用
const
属性使用
readonly
超额检查
1 | interface SquareConfig { |
你可能会认为此程序输入正确,因为width
属性是兼容的,没有color
属性存在,并且额外的colour
属性是无关紧要的。
但是,TypeScript认为此代码中可能存在错误。Object literals 在将它们分配给其他变量或将它们作为参数传递时,会得到特殊处理并进行多余的属性检查。
如果Object literals具有“目标类型”没有的任何属性,则会出现错误。
1 | // error: 'colour' not expected in type 'SquareConfig' |
colour 是多余的,target type 中是没有的
解决这个问题:
- 断言
1 | let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig); |
index signature(索引签名)—
如果您确定该对象可以具有某些特殊方式使用的额外属性
如果SquareConfig
能有color
和width
上述类型的属性,但可能也有任意数量的其他性质的,那么我们就可以像这样定义它:
1 | interface SquareConfig { |
- 赋值给一个变量
1 | let squareOptions = { colour: "red", width: 100 }; |
Since squareOptions
won’t undergo excess property checks, the compiler won’t give you an error.
Keep in mind that for simple code like above, you probably shouldn’t be trying to “get around” these checks. For more complex object literals that have methods and hold state, you might need to keep these techniques in mind, but a majority of excess property errors are actually bugs. That means if you’re running into excess property checking problems for something like option bags, you might need to revise some of your type declarations. In this instance, if it’s okay to pass an object with both a
color
orcolour
property tocreateSquare
, you should fix up the definition ofSquareConfig
to reflect that.
接口中声明函数
1 | interface SearchFunc { |
1 | let mySearch: SearchFunc; |
参数名可以不用匹配,下面这样也是可以的
1 | let mySearch: SearchFunc; |
Indexable Types(可转换类型)
Indexable types have an index signature that describes the types we can use to index into the object, along with the corresponding return types when indexing
1 | interface StringArray { |
Above, we have a
StringArray
interface that has an index signature. This index signature states that when aStringArray
is indexed with anumber
, it will return astring
.There are two types of supported index signatures: string and number. It is possible to support both types of indexers, but the type returned from a numeric indexer must be a subtype of the type returned from the string indexer. This is because when indexing with a
number
, JavaScript will actually convert that to astring
before indexing into an object. That means that indexing with100
(anumber
) is the same thing as indexing with"100"
(astring
), so the two need to be consistent.
1 | class Animal { |
While string index signatures are a powerful way to describe the “dictionary” pattern, they also enforce that all properties match their return type. This is because a string index declares that obj.property
is also available as obj["property"]
. In the following example, name
’s type does not match the string index’s type, and the type-checker gives an error:
1 | interface NumberDictionary { |
Finally, you can make index signatures readonly in order to prevent assignment to their indices:
1 | interface ReadonlyStringArray { |
can’t set myArray[2]
because the index signature is readonly
疑问:签名索引和这个可转换类型 相似
类
1 | interface ClockInterface { |
Interfaces describe the public side of the class, rather than both the public and private side. This prohibits you from using them to check that a class also has particular types for the private side of the class instance.
混合类型
1 | interface Counter { |
与第三方JavaScript交互时,可能需要使用上述模式来完整描述类型的形状
3.类
传统的javascript构建可重用的组件是使用函数和基于原型的继承
类的写法形式:
1 | class Greeter { |
复杂的继承的写法:
1 | class Animal { |
tom 仍然使用的是Horse重写的move方法
修饰符
public(默认)、private、protected
private
TypeScript是一种结构类型系统。当我们比较两种不同的类型时,无论它们来自何处,如果所有成员的类型都是兼容的,那么我们说类型本身是兼容的
1 | class Animal { |
However, when comparing types that have private
and protected
members, we treat these types differently. For two types to be considered compatible, if one of them has a private
member, then the other must have a private
member that originated in the same declaration. The same applies to protected
members.
我的理解:
虽然都是 Private 声明的同名变量,但一个是这个一个是那个,就像有两个具有相同属性的对象,还是不一样的,所以解释中说,必须来自同一个源,
protected
是可以在子类中访问,但是也是不可以在子类的外面访问的。
1 | class Person { |
protected标记构造函数,这意味着该类不能在其包含的类之外实例化,但可以扩展
1 | class Person { |
使用 protected 标记的构造函数,在类的外面是不能访问的,但是可以在子类中访问
- 构造子类
- 子类构造方法中 super 调用父类的constructor
但是是不可以直接在外面使用 new 的方法构造一个对象的。
又出现的readonly
1 | class Octopus { |