typescript 零散的
typescript in vue
props type
<script>
import { defineComponent } from 'vue';
import type {PropType} from 'vue';
type Resturant = {
id:string
people:Array<string>
total:number
anyThing:any
}
export default defineComponent({
props:{
resturant:{
type: Object as PropType<Resturant>,
required: true
}
}
})
</script>
advanced ttypescript
TIP
tsc ts.ts && node ts.js
可选链
//advanced typescript fundamental
type SerialicationOptions = {
formatting?:{
indent?:number;
};
};
function serializeJSON(value:any,options?: SerialicationOptions){
const indent = options?.formatting?.indent??2;
return JSON.stringify(value,null,indent)
}
const user = {
name:"ajn404 n-gray-moon",
bilibili:'狗粮长'
}
const json = serializeJSON(user,{
formatting:{
indent:0
}
});
console.log(json);
编译后
function serializeJSON(value, options) {
var _a, _b;
var indent = (_b = (_a = options === null || options === void 0 ? void 0 : options.formatting) === null || _a === void 0 ? void 0 : _a.indent) !== null && _b !== void 0 ? _b : 2;
return JSON.stringify(value, null, indent);
}
var user = {
name: "ajn404 n-gray-moon",
bilibili: '狗粮长'
};
var json = serializeJSON(user, {
formatting: {
indent: 0
}
});
console.log(json);
断言和谓词
File not found
编译后
function assertIsNumber(value, name) {
if (typeof value !== "number") {
throw Error("Expect \"".concat(name, "\" to be a number"));
}
}
function range(from, to) {
assertIsNumber(to, 'to');
assertIsNumber(from, 'from');
var values = [];
for (var i = from; i < to; i++) {
values.push(i);
}
return values;
}
console.log(range("A", "F"));
NonNullable
function assertIsNonNullish<T>(
value:T,
message:string
):asserts value is NonNullable<T>{
if(value===null||value===undefined){
throw Error(message);
}
}
const root = document.getElementById('app');
assertIsNonNullish(root,"找不到#app的dom元素");
root.addEventListener("click",e=>{
console.log(e);
})
编译后
function assertIsNonNullish(value, message) {
if (value === null || value === undefined) {
throw Error(message);
}
}
var root = document.getElementById('app');
assertIsNonNullish(root, "找不到#app的dom元素");
root.addEventListener("click", function (e) {
console.log(e);
});
private
class Counter {
private _value = 0;
increment(){
this._value+=1;
}
get count(){
return this._value
}
}
const couter = new Counter();
couter.increment();
couter.increment();
couter.increment();
console.log(couter.count);
编译后
tsc ts04.ts报错
ts04.ts:7:9 - error TS1056: Accessors are only available when targeting ECMAScript 5 and higher.
7 get count(){
~~~~~
Found 1 error in ts04.ts:7
使用tsc ts04 -t es5
实现private使用了weakMap
编译后
var Counter = /** @class */ (function () {
function Counter() {
this._value = 0;
}
Counter.prototype.increment = function () {
this._value += 1;
};
Object.defineProperty(Counter.prototype, "count", {
get: function () {
return this._value;
},
enumerable: false,
configurable: true
});
return Counter;
}());
var couter = new Counter();
couter.increment();
couter.increment();
couter.increment();
console.log(couter.count);
closure闭包
function createCounter(){
let value= 0 ;
return {
increment(){
value++;
},
get coute(){
return value
}
}
}
const couters = createCounter();
couters.increment();
couters.increment();
couters.increment();
couters.increment();
console.log(couters.coute);
编译后
function createCounter() {
var value = 0;
return {
increment: function () {
value++;
},
get coute() {
return value;
}
};
}
var couters = createCounter();
couters.increment();
couters.increment();
couters.increment();
couters.increment();
console.log(couters.coute);
//4
readonly array type
function intersperse<T>(array:readonly T[],separator : T):T[]{
const newArray:T[] = [];
for(const element of array){
if(newArray.length!==0){
newArray.push(separator);
}
newArray.push(element);
}
return newArray
}
const values:ReadonlyArray<string> = ["A","B","C","D"];
const valueWithSeparator = intersperse(values,"X");
console.log(values);
console.log(valueWithSeparator);
编译后
function intersperse(array, separator) {
var newArray = [];
for (var _i = 0, array_1 = array; _i < array_1.length; _i++) {
var element = array_1[_i];
if (newArray.length !== 0) {
newArray.push(separator);
}
newArray.push(element);
}
return newArray;
}
var values = ["A", "B", "C", "D"];
var valueWithSeparator = intersperse(values, "X");
console.log(values);
console.log(valueWithSeparator);
readonly tuple type
function swap<T,U>(tuple:readonly [T,U]):[U,T]{
const [first,second] = tuple;
return [second,first];
}
const keyValuePair: readonly[number,string] = [1,"one"];
const valueKeyPair = swap(keyValuePair);
console.log(keyValuePair);
console.log(valueKeyPair);
编译后
function swap(tuple) {
var first = tuple[0], second = tuple[1];
return [second, first];
}
var keyValuePair = [1, "one"];
var valueKeyPair = swap(keyValuePair);
console.log(keyValuePair);
console.log(valueKeyPair);
as const
const ORIGIN ={
x:1,
y:1
} as const;
ORIGIN.x =10;//无法分配到"x",因为它是只读属性
上述运行时不会报错,但下面这种会
const freezeOrigin = Object.freeze({
x:1,
y:1
}as const)
freezeOrigin.x = 1;//无法分配到"x",因为它是只读属性
as const用于数组
const ORIGIN ={
x:1,
y:1
} as const;
ORIGIN.x =10;//无法分配到"x",因为它是只读属性
use const asserts in enum-style obj
const HTTPRequestMethod = {
GET:'GET',
POST:'POST'
}as const;
type ValueOf<T> = T[keyof T];
type HTTPRequestMethodType = ValueOf<typeof HTTPRequestMethod>;
async function fetchJSON(
url:string,
method: HTTPRequestMethodType,
){
const response = await fetch(url,{method});
return response.json();
}
fetchJSON("http://",HTTPRequestMethod.GET).then(res=>{});
编译后
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var HTTPRequestMethod = {
GET: 'GET',
POST: 'POST'
};
function fetchJSON(url, method) {
return __awaiter(this, void 0, void 0, function () {
var response;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, fetch(url, { method: method })];
case 1:
response = _a.sent();
return [2 /*return*/, response.json()];
}
});
});
}
fetchJSON("http://", HTTPRequestMethod.GET).then(function (res) { });
所谓NonNullable
type NonNullable<T> = T & {};
type NonNullable<T> = T extends null | undefined ? never:T;
type A = NonNullable<string>;
type B = NonNullable<null>;
应用
type EmailRecipient = string | string[] | null | undefined;
type NonNullableEmailRecipient = NonNullable<EmailRecipient>;
//等同于
//type NonNullableEmailRecipient = string | string[]
所谓ReturnType
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
name type parameters
type ReturnType<TFunctions extends (...args:any)=> any> = TFunctions extends (...args:any) => infer TReturnType?TReturnType :any;
template in ts
比如css类型
type Dimention = 'block'|'inline';
type Direction = 'left' | 'right' | 'top' | 'bottom';
type MarginProperty = `margin-${Dimention}-${Direction}`
//type MarginProperty = "margin-block" | "margin-inline"
type MarginUnit = 'px'|'vw'|'%' |'vh';
type MarginValue = `${number}${MarginUnit}`
type MarginPropertyDeclaration = [MarginProperty,MarginValue];
// const margin :MarginPropertyDeclaration = ['margin-block-left','12'];
//不能将类型“["margin-block", "12"]”分配给类型“MarginPropertyDeclaration”
const margin :MarginPropertyDeclaration = ['margin-block-left','12px'];
相对复杂的案例
//“相对复杂“
// type Record<K extends keyof any, T> = {
// [P in K]: T;
// };
type PropGetters <TObj extends Record<string,any>> = {
[Tkey in string & keyof TObj as `get${Capitalize<Tkey>}`]:()=>TObj[Tkey];
}
function createGetterObject <TObj extends Record<string,any>>(obj:TObj):PropGetters<TObj>{
const newObj:any = {};
for(const key of Object.keys(obj)){
const capitalizedKey = key[0].toUpperCase()+key.substr(1);
const getterKey = `get${capitalizedKey}`;
newObj[getterKey] = ()=> obj[key];
}
return newObj
}
const user = createGetterObject({
id:123,
name:'王德发',
phone:12510102031
})
console.log(user.getId);