TypeSctipr Version4.6.4
string number boolean undefined null object symbol never any unknown Array Function
let arrays: Array<number> = [1, 2, 3]
let number_arr: number[] = [2, 3, 4]
这两种使用方式一样
当没有使用到类型注解、ts 通过上下文也不能推断的就会默认使用 any 类型
let unImmuable: any = 1
unImmuable = function () {}
unImmuable = true
可以在 tsconfig.json
中开启 noImplicitAny = true
来使 ts 不回默认使用 any 类
型
一般在一些变量命名时候不需要对其进行类型注解 只需要赋予值就行 然后 ts 能自动对其 类型注解。
// 哒咩
let a: number = 333
// 要洗
let b = 333
这里就涉及到了最基本三个知识点了
1、函数的参数类型注解
2、函数的返回值的类型注解
3、匿名函数中的参数类型注解
当使用函数的时候会通过检查你的类型注解来去判断是否使用正确
function pritName(first: string, laster: number) {
console.log(first + laster)
}
在声明函数的的时候在每一个参数后面跟上 类型注解
function pritName(first: string, laster: number): string {
return first + laster
}
当 ts 知道如何调用 匿名函数 时候就会自动的推断其使用的参数类型是什么这个过程称之
为 上下文推断
let arrs = [89, 'Perter', true]
arrs.forEach((element) => {
console.log(element)
})
ts 能自动的推断出其参数的类型为 element: number | string | boolean
语法: () => void
例如: (a: string ) => void
function Peer(str: string) {
console.log(str)
}
function geteeter(fn: (a: string) => void) {
fn('Hello')
}
geteeter()
函数的参数没有明确给出就会默认为 any
在 tsconfig.json
中设置 strict
noImplicitAny
的开启都会导致程序中报错
类似的还可以使用 type
类型别名去定义一个 函数类型
type Peer = (a: string) => void
函数除了可以被调用还可以有自己的属性值 如果我们想描述一个带有属性的函数,我们可 以在一个对象类型中写一个调用签名(call signature)。
// 函数签名
type Des = {
description: string
// 这里就表示函数的返回值是一个 布尔值 且返回类型之间使用 `:` 而不是 `=>`
(someArg: number): boolean
}
function doSomeSting(fn: Des) {
fn()
//....
}
function fn() {
return true
}
fn.description = 'string'
doSomeSting()
JavaScript 函数也可以使用 new 操作符调用,当被调用的时候,TypeScript 会认为这是 一个构造函数(constructors),因为他们会产生一个新对象。你可以写一个构造签名,方法 是在调用签名前面加一个 new 关键词
type SomeConstructor = {
new (s: string): SomeObject
}
function fn(ctor: SomeConstructor) {
return new ctor('hello')
}
调用签名和构造签名可以放在一起
interface SomeConstructor {
new (s: string): Date
(n?: number): number
}
函数的输出类型依赖于输入类型,或者两个输入类型以某种形式相互依赖
function firstName<Type>(arr: Type[]): Type | undefined {
return arr[0]
}
// 调用
const value = firstName(['a', 'b', 'c'])
// typeof value === string
const Value_2 = firstName([1, 2, 3])
// typeof value_2 === number
这里指定了一个参数为 Type[]
的类型(也就是说接收 Type 类型的数组) 且 输出值也
符合 Type
的类型(值为 Type 类型)
ts 会根据上下文来推断类型参数
function map<Input, Output>(arr: Input[], func: (arg: Input): Output): Output[] {
return arr.map(func)
}
有的时候,我们想关联两个值,但只能操作值的一些固定字段,这种情况,我们可以使 用**约束(constraint)**对类型参数进行限制。
比如: 为了确保传入的参数具有 length
属性我们使用 extends 语法来约束
function <Type extend {length: number}> (a: Type, b: Type) {
if(a.length > b.length){
return a;
}else{
return b
}
}
这是一个错误的例子
function minimumLength<Type extends { length: number }>(
obj: Type,
minimum: number
): Type {
if (obj.length >= minimum) {
return obj
} else {
// 这里出现问题
return { length: minimum }
}
}
这是一个返回值类型为 Type
的函数 函数返回值不符合要求 就会出现错误
虽然这个例子返回的 对象符合 约束
但是和参数的类型 Type
不相符
ts 能自动推断泛型调用中传入的类型参数, 但也并不能总是推断出
function combine<Type>(arr1: Type[], arr2: Type[]): Type[] {
return arr1.concat(arr2)
}
combine([1, 3, 5], ['hello'])
// 这里就会不合适 出现错误
// 可以手动的添加类型
combine<string | number>([1, 2, 3], ['hello'])
// 类似于这种
let arr: (string | number)[] = [1, 2, 3, 'heool']
// 这 `string` 和 `number` 之间做了一个并集 可以处理的范围更广
1、参数可选 需要在参数的后缀一个? 表示参数可以省略
function f(x?: number) {
//...
}
2、参数提供一个默认值
function f(x = 10) {
//....
}
3、回调函数的可选参数
在 4.6.4 版本中
function myForEach(arr: any[], callback: (arg: any, index?: number) => void) {
for (let i = 0; i < arr.length; i++) {
callback(arr[i], i)
}
}
myForEach([1, 2, 3], (a, i) => console.log(a, i))
回调函数中 index
的参数是一个可以被忽略的 但是传入了一个值 ts 没有抛错可以使用
。 这里表明了 回调函数可以接收 1-2 个参数值
ts 的函数调用中 确定其参数后才能对其使用 但是有些函数需要根据不同的参数的来返回
值。这就需要写 重载函数签名
才行, 通过写一些函数签名
来说明函数的不同调用方
法
function makeDate(timesTamp: number): Date;
function makeDate(m: number, d: number, y: number): Date;
function makeDate(morTimestamp: number, d?: number, y?: number){
if(d !== undefined && y !== undefined){
return new Date(morTimestamp, d, y)
}
else if(d !== undefined || y !== undefined){
return d extends undefined ? new Date(morTimestamp, d) : new Date(morTimestamp, null, y)
}
else{
return new Date(morTimestamp)
}
}
这里有两个函数重载
一个接收一个参数 另一个接收两个参数,然后又写了一个兼容签名
的函数实现 将其称之为 实现签名
这里的函数调用只接受 1 或者 3 个参数 原因就在于没有写 接收 2 个参数的函数重载
函数重载 和 实现签名必须兼容
1、尽量使用 联合类型
代替 函数重载
function len(s: string): number
function len(arr: any[]): number
function len(x: any) {
return x.length
}
等效于
function len(x: any[] | string) {
return x.length
}
const User = {
id: 123,
admin: fasle,
bacomeAdmin: function () {
this.admin = true
}
}
在这个对象 User
中 this
能够知道是指向的是 User 在特殊情况下还需要明确指出
interface User = {
id: number;
admin: boolean;
}
declare const getDB: () => DB;
interface DB {
filterUsers(filter: (this: User) => boolean): User[];
}
const db = getDB();
const admins = db.filterUsers(function(this: User){
return this.admin;
})
这里就去指明了 this
的指向关系 this 代表着 User
值得注意的是这里不应该使用 箭头函数 箭头函数的 this 指向的是外层函数的 this
1、void
表示一个函数不会返回任何值。
2、object
表示任何不是原始类型的值 (string, number, bigint, boolean, symbol, null, undefined)
3、unknown
表示任何类型的值 类似于 any 使用 unknown
更安全怎么使用都合法。可以描述一个函
数返回一个不知道什么类型的值。
function printAny(num: string): unknown {
console.log(num)
}
4、never
一些函数从来不返回值,它也表示一个值不会再被观察到,作为函数的返回类型的时候他会 表明 函数异常结束,或者是会结束程序执行。
function fnc(s: string): never {
throw new Error(s)
}
也可以表示在联合类型中没有可能是其中的类型的时候
function fn(x: string | number) {
if (typeof x === 'string') {
// do something
} else if (typeof x === 'number') {
// do something else
} else {
x // x 的类型 type= 'never'!
}
}
感觉这样写体现不出来这个特征 当函数的参数不是 string | number
的时候就会抛出错
误的。