类型兼容性

TypeScript 中的类型兼容性基于结构子类型。结构类型是一种仅基于其成员关联类型的方法。这与名义类型相反。考虑以下代码:

interface Pet {
  name: string;
}

class Dog {
  name: string;
}

let pet: Pet;
// OK, because of structural typing
pet = new Dog();

在 C# 或 Java 等名义类型语言中,等效代码将是错误的,因为 Dog 类没有明确将自己描述为 Pet 接口的实现者。

TypeScript 的结构化类型系统是根据 JavaScript 代码的典型编写方式设计的。因为 JavaScript 广泛使用匿名对象,如函数表达式和对象字面量,所以用结构化类型系统而不是名义上的类型系统来表示 JavaScript 库中发现的关系类型要自然得多。

关于健全性的说明

TypeScript 的类型系统允许某些在编译时不知道的操作是安全的。当一个类型系统有这个属性时,就说它不是"sound"。仔细考虑了 TypeScript 允许不合理行为的地方,并且在整个文档中,我们将解释这些情况发生的位置以及它们背后的激励场景。

开始

TypeScript 结构类型系统的基本规则是,如果 y 至少具有与 x 相同的成员,则 xy 兼容。例如,考虑以下代码,其中涉及一个名为 Pet 的接口,该接口具有 name 属性:

interface Pet {
  name: string;
}

let pet: Pet;
// dog's inferred type is { name: string; owner: string; }
let dog = { name: "Lassie", owner: "Rudd Weatherwax" };
pet = dog;

lqg8+szFmDcYFYTwy/l/n5T1x/RcfDQ18GmHtAgtM0HW5Sak8qQ4UydH9s0PIHwuOJghskZ6EWaay596WrqVI2ADKedieFN2yo+R/UxNmCHPm6JbcqM7Obo7Qv7l12JDd+xSO4QkfViurOzgFNoefdKvVQ/lR6WriBrbabfpJhmdz2QbqTVopA3XpQPp0ta9Ctttw47j6HFlq4mQpjtDGYiOpbcew2AMkA6RnlXfcJkMlI+DG5qZXLiXZdRTGW+g1sP0cPfnKrN2+ZSxxdxEwLU5EcttafI4eyc/Gp7pLOOaPIfakmcS6yjOYVi8yqboofiijOyDtcEYYMtiuiQYO0khPBO+01TXPXM5NxUWp9zVuMUXv4IXKutKMDipwLIDXqa4a31AY3AyZNsDNofgjZRhxzE34LER2J+YndkFH3HtQfedWn3TzExjJTkselF7

FYTsHsksexzCAQIzKxqgbvOA+1hQjFrs5+lcW3vbjs5NNhPMTUEB3k0l4W4T7CA2gcPX7AWK6qAx+dC/pEFT7Q==

interface Pet {
  name: string;
}

let dog = { name: "Lassie", owner: "Rudd Weatherwax" };

function greet(pet: Pet) {
  console.log("Hello, " + pet.name);
}
greet(dog); // OK

gdnPvxzxrOCUJDsNiIK+/4pOl/1rmS2Ds6eBscnAgZAtr2KZwS+HuKlNvEp3/xCgPO4D8kPJSiCjy9UzVTKQJ3gJZIyK/kG8ijsRzBeMZGA5KnL8jJQ+Q0+LBKaChkzrcB4pszLnpyJdEaL7oW1VLiL1E0eLIxWWEIn5O+Y8DT8dfVBp33J6FhEiDaKnJCCt8nGm4SAhh/HiiwXvbAGJxmIdCF6TtOePum0Il5HA2Xxci8SK0AMRj1dCo+Qd5pKRMh33OYtXpKLMswr8ctqpTQ==

p7BeuFWrplwqtqqwYz+Jzdyq3TaG9pQ1w9/Vz6BBynW7Jkgt0w3qIHZb65Sv5PyI2TjShnfiIiM2Bm6K5BiaBkT07phkU3jhCNeQtuBdJwI=

比较两个函数

0/oTzEPFt4p9qPsm5CgmP0Dw9kgnTRn3sW9QHUri3edclDUpSq5Ye7+QpBoVOCdNL+720ZyvfUtoMVrn105H2PI/vrrhM5fxmInnHObpHboY0Ms2p55Hp2yzX94ZgeFnQeIm9aoUBRctQ1tdOqeHwT8WHipVNIjyObUckx6jTF7IqjE/wqqCVwWpsvf0z5owoc1ey6x+9NkmUKAmjy89WOrKwTMoykqgo8Jtvk5roxOqT2SyfLB9V1QpHYuw2lvHMrdlXq+gI99AJX/X61tst9rXeI4pFQ7IcEjB6x5/swc=

let x = (a: number) => 0;
let y = (b: number, s: string) => 0;

y = x; // OK
x = y; // Error

kXv/8ZwkqCXnYkFK1Cn47DsoHPUjc7GAAjDWdGdg/Xwa4aMzngB1jc2Au+xSQncYC7lYjNP8l9cIxKMrzMGZbzzyjxvY/wWj/edyA1NYFEyZZCajkkcK3Xnh0bWYVyfKheagraOFVlkM8Xk1MNeHaG4QpNXE1R0qxpAR8qMjyH1k/d9K+lL7GERSNWNpJg4DyS7c0jVcKieQAdBJ4uVHqG22NLemyC17lByxNUfbiKKnOzEdYWx5BGUNP2bcGBVwpNbCs0ZlD1bSrlCWYCQfMRBF+4fwTMP1dB+0sTupfaz3cp2xDzGy1c2/x/wXCXc5q01K4FqLEVxVY6x701O+SjwgFo2zMlWbuEHf3w8cgCFTZ/ui7o+P2lRUR/n4J8aoWPeohygCL85InFz8PJG9Ljn+RIW8iH/KlkIiH7P6YNdaEGg9SJsjiXIbMFpWqBzsedb8SXgdai9PJ7YRweds1UFcx5OPPldTSdNQaqsHMxD1n9nCYDpYTGnhh5haWoPZ8tRWrK/quDGDf6puCk3OQw==

DP6vi3B95rQORwfd0qAiYC391hq4/en6H/0RCa05kxv0xjCTiRJIY1mpoPzu8Tr9OnUsVDPYK7SWD1CzL6WqMa4hdQvtTJXnwxRbp3Y4kMHvrGjsoijXZxEnUvg8KueZQBENmEpfZo8GYeeGap5G4iIR1A30DeQy+LThBScMiMCBdC69h6lv60eydooTISZd

LxTPncgoaYlxUq7gkgcLKHx6J5/PLEUdM8bQsNwctQNm5LZuicvuE7j53p7dg7vD3GwgzGiF+s/WYvwhnpSOdmIz2qvdiV6cStM6QuuHx4yuKd3Lqq3eDIXXMFKcOu2MFG6fnLmb2hcIAdfZdlz6EWNpxeO1qtXSwxOsObo21veCtwr2K+KzjyUAtFS3yVayTZ77cNmyqqdS5w30z5DuFv4KfSyp8LZr5lN2iHj6Hc80p9sSE3kBgpM13llXbBFOCcnfBA1iKcP/1QSpGsYhOdyYVsz/FTa8XeVYuXVFgnnFN8i7VpoNj7EgFKEdpAaZZe5NcccZNRdu19OFN8JERE0fT9UvBJMFpgdPQp9uOKNgEDnbV1E4vNJqchQZQx+NsA76Gju1k7o5aLa9a9aLwLucL8MWL7hI+Eq/cVXFbAyAwAo3AhkqS4cK302q+I7HkSKeMX7AZnbu835IRFtNgduVrdFXW3X/sc3sc3be+lX6RAOwAcarZnXmEoF2QVXQ

let items = [1, 2, 3];

// Don't force these extra parameters
items.forEach((item, index, array) => console.log(item));

// Should be OK!
items.forEach((item) => console.log(item));

+iMBSfNkNGPy63WXCxZ3bv9qGpdmqLJHLNOkqzdXvxGqB+RTxoYeqoL+nbsn1ovFhug3m7+r6f8xbsha6Rk7kmrHJEjbRgYVkTwqIPSDY1Qf1CkDFLj/6adH46TUTmU8

let x = () => ({ name: "Alice" });
let y = () => ({ name: "Alice", location: "Seattle" });

x = y; // OK
y = x; // Error, because x() lacks a location property

bx3ynkIOKoCQOcfMEhk8kEWk8TGJl8pq0AtOfuLdNL499MOZYUnLKVSo7w8b8uraLLWUdn48q+Fo5iCB+69jvFJyTSsqlFB5flZvhPIuo8Ata47ds6TuYKxiazol79Bz

函数参数双方差

wLW5b3mE/2NI3C/3AuGorSZPPxKHtj2iXYQSaS4PfnVLHAW5T+B0p+qbpRcidXSdh5JdLfUATAAA8gaxGrDtJj8b9HKxmJIhyBcpGEDeLGKxCtafoVybfa6+9TT+qNlIHRqqlqgRxwRNZcrXkff3v/KFLAkn1sRYnzBra+lYAmh4KgweeXbc/fpZvn37RXlqdhKUMvFlSxO3vDymH9ih4RMaBbLGzHjsdRHLeWaiD5Rl4VyPaZPf6HxfTuPVmUC71J6DfNCxITbM6W9fqiHeDRvVJMsXQNH6yo4SsjuL9DykF/aBl2LdDxMZtytxymZ9k3We72oy3m98vQr5Pgsv5VQyZxEcfEbpbh4SHIX21MVymxxFo+GZkQ5A0r5I7jCFf27vxlZw7p5X0XLaoZouGwyo6KIe/eZorjBCJ/LQo/Zm04TFMnpRokOtZp6PbimX+jIxOlmbTVwDSK/EaDnVRnDSzz+Jgi5VGizOlqW5BVhf2T/l8r3QW75a2oKQ3Dw7

enum EventType {
  Mouse,
  Keyboard,
}

interface Event {
  timestamp: number;
}
interface MyMouseEvent extends Event {
  x: number;
  y: number;
}
interface MyKeyEvent extends Event {
  keyCode: number;
}

function listenEvent(eventType: EventType, handler: (n: Event) => void) {
  /* ... */
}

// Unsound, but useful and common
listenEvent(EventType.Mouse, (e: MyMouseEvent) => console.log(e.x + "," + e.y));

// Undesirable alternatives in presence of soundness
listenEvent(EventType.Mouse, (e: Event) =>
  console.log((e as MyMouseEvent).x + "," + (e as MyMouseEvent).y)
);
listenEvent(EventType.Mouse, ((e: MyMouseEvent) =>
  console.log(e.x + "," + e.y)) as (e: Event) => void);

// Still disallowed (clear error). Type safety enforced for wholly incompatible types
listenEvent(EventType.Mouse, (e: number) => console.log(e));

cftxRFefbigYUWRFaArSz+9Tu2Qqx9oSy04T8/41bzoEN64Oe1YNqeVxCjp9XdGTAgx2fzCxiGWBPGiXo4NJqoD1hWBeIUk7S27rEFOcwvXyWFC7CoesRVULzKLmZvMb8iltsrFi0S6+YETKm7ezBs7t0tKTPhBEK0UiNidwEH31uyWIBkU1sMcVpp406eKVbDtbGfCsz4nx8WXsffBOF8SrQo1fYIDv9P4Il3s3osk=

可选参数和剩余参数

rX82JbCVM2SqciXM5AXfKoyh/BE2f9V5LrFixg3RLj5x968KrKop6+ckA7C3wJEH9/AaO0eQ6HDrVPXCDAqKkddEgYxAzy5eF65E3D3GSM3yvT4p/3FI9pOuVP6UWWzBBgMbIgum1Lt9mhanTAubgs61vmm/Zq57QheDo7Rz+nQxyno2pNnVmXCTsRZKDPJ9H/eot/FwcDUQGjDZJw3i+YV5i0vZSghca6pQB7Fck8lhqNbCzwnfbT9rtY5UYj2mKmaoEP8LrmMW5MBEdkd5uw==

C1hb28BGs+4x2X685voHDZoKHMbC3EfPkTDTR2tEubJ3sN9HT6kv1dlPZXob7Pjo6PYOlFr8iQI0l3HLBRTY0FFTXHgr1acWXSP8ueLQMZ1e/4j0GUlooO5mrwECp8DW

whIAsL1ktk/RsyO+2GY7F8YUiIfBFq1rshbv+/lRkD1a1EX9t261zIG6hAbJRtwZWJMQrNPQXueobiCpUZTo+DuA9qV4R9Cjtb0b2R/DOoZR6J1tkW9qUR4ytSTSclvid2tLHC3Cx8yf847VHa0G62hqYeZfrdiBeAz5vE9ygbbgnch4+jBV+DZQ+VqlWwEPlbzbG7nUlH9sJ5IXN2OX7HHqcObd+JRoGJ56SkDdG6+CZTSrwtHky8NO7ofAN6gkVC2xhwttNLfGULpAXhDJqQwIyt4fj5XDV7Du/Q5jGnqh2qAIVuIPS5jSSGA+8FwP

u/uqQ9JRsk1cnxyQ4JgFJEhKJ8tDjbMd+5tVH2Kms74PymKoNlz6dMy2Xgi9Wh5WrwARWcDV78MwaN0SNoFxxCe2dvWEG6jxhq4Rzk6zzh1IX2BVz0lx4G0IsotC9Qoh8NT44T77hfSndZZ6sulgAWTQwBizsOU2Vc7lKXojQmoFkFQtYOFCVDm10Qdkxen/FG/nJPUG1lyWcDoC5BjDZz9XSOkg72FEXWWvuf7I/rM2/qdXE6j/brtwA1cjlVMA

function invokeLater(args: any[], callback: (...args: any[]) => void) {
  /* ... Invoke callback with 'args' ... */
}

// Unsound - invokeLater "might" provide any number of arguments
invokeLater([1, 2], (x, y) => console.log(x + ", " + y));

// Confusing (x and y are actually required) and undiscoverable
invokeLater([1, 2], (x?, y?) => console.log(x + ", " + y));

具有重载的函数

0skz0SeQg+Tbij4Qj3oaW5MT319/dvYbiJqu6A1OOa9f5wNES84cFu9V1nYZIRhW+GskmIEK+r6cOr9hYA+8BKIA3QL2FZNLTRIhFLK16HPZoHt6u4fxboy7bnswPHH0VMBDSTHQJL+FSIX7i/ZRRn7LVOHPyvMvgVI7AfEeO7AYn21pgG7V5groTd2hFRUpELOvQDV2J/r0J2R0AHDbsnzdLAfVbFAJS+QI4TNQq2ZzU4EwYMInd6f8RCnAYiqu

枚举

N9aq7MnG0YK1iM35dh8IFeZAvtDbXBH2slehc3M308gvkloSRSUz7iOJLzX4BcLNVceCxHcKWbaqmXiBoqx+HZ60PtykLlOvWQ1u4jCpjbCaWu28crBAIfhTcOLAwl+4WewhjtzEEfIdn2H/W5WZ6CQvqREEmda3cYlxNEBInK4=

enum Status {
  Ready,
  Waiting,
}
enum Color {
  Red,
  Blue,
  Green,
}

let status = Status.Ready;
status = Color.Green; // Error

ebs91aDKI/fCYNUC9F2WlgVuK3sAoSZWYjMleMHDYP7HH3/TvOipn706VmpBnMhnEPWqTWm6ZnYMS8ISiWLUoCmi1aokg9CDH6/T9SDEGI3cGte5x0oTxGJLruR07rsgXCYVmoDZwK2mwvU7HolK4J1IRroV6DRg5Sj7f3Ndt7qhuRmWGn5eRhWtjx2HXCj0LqoO6eS4FZKGXTWaqNaerRqTuEmlbmPDSCpa9is2C3GbcDU82LRNk8PDunykCxEnWpCSf3AOd2HoSYL2Z/0UL7qwlQPMwxEEJGS1lG9PPSFQAsD10jjNsTJ+xetZO3mFxHXmFMaynG4mKAEdwfoJfA==

class Animal {
  feet: number;
  constructor(name: string, numFeet: number) {}
}

class Size {
  feet: number;
  constructor(numFeet: number) {}
}

let a: Animal;
let s: Size;

a = s; // OK
s = a; // OK

类中的私有成员和受保护成员

LirK55XCOx1bcVRYIyWm/KUjpgaIAaGHpHG5V58FK/tsv3a5oeNK2lH2H29JV5Y8sPrJNaqzMwi+lvBwKqNRqCdQdqp2AIo+Wo9awpEB+aoA0IAt3mBlhFLJXm8ypg3qKQMpjHKqdl4rmHXK3MxEVBxC+cG49KOgMnOQBbLomH45L94SspJ/MwV69e/b78uXJxVARvE+zeun6PYxhHn/ujB4QAovlVU4KM5yNVCBab+M1EWsgXrpz0v8duImDp6KVVmXvTYt3h1yR0jhNRDLST17EfgaYlea2WzjNpqhxLhCgl4CPZGmZvs8rJNyMRoodmVBTrM1Y6Jyt6vcjvn2tvbxzrS/XfWX52nVwZWWSfEWUk1AwaapxocdgJiQK8DrXW7itQ2AJGQlBFP1IcKfc1hXLTiTdMjTo/nth8Q3C1u93M3JIpPO6zfX1O8jsYn++L2xHPpDNeJCJ+XMx5mnwgDx+RvHk0ZVXxVk9REBtfh/VPBClNTuZnYpzyZaKsZ2UJe01JEBNe6BjVk6nBjCld99ldTZqmdeVga2lVa8FWs=

泛型

DyPjsdhrgMg0cDt5AGu7caST1khMgmRndsxmEmaSW70ArHo+4dypGmN917tRntiuSMbkD3rkiu9BeY9cgnj6LIAsAnr/utE3kDb+0O6X9j3fsnI8RxnpXoQgrDXacSu/mWoHnJbreXXiZgiuNvnf/yQ6YARZFIJVvWehjjYZEaZp4aauKQMMeAFz+IWZnrGPTlrataGNeED4MosaCW1i1Q==

interface Empty<T> {}
let x: Empty<number>;
let y: Empty<string>;

x = y; // OK, because y matches structure of x

j288vfxWvZFS/b34jcihze15NYNCksMhD+FnDK/4L24poe0rOEPo8ex1cXGWtyPxdz6myl4vHStw747nODuO93U0oBQ6rNLWYJU5qrV6ROaH+NVxBVXoJ7slz90c3pdoNgEardm4aiuNE8qug8gHrmMtdNqQNOvyaHJ5vhfdlwFyTjW6vqxj2nw3jlVodcTWMtDDn5QrVHABR9oENtNR6DqtEcOX84nBy01K7e7hlLc/GjZAjmNQYXJgXAdI742OBaWKeBl76k/n2dQjRdrl5mN8mj6C5ge5J1672lWRs20=

interface NotEmpty<T> {
  data: T;
}
let x: NotEmpty<number>;
let y: NotEmpty<string>;

x = y; // Error, because x and y are not compatible

VBnbEty5ue050x1ekAfmkatGLTx95nva8tOjL8j9khq6V/lZ2M45OZ1JiV+fbug7ytDL2O+h9K6sox0po/xrnVSl90Z9Svk9rkY1MEuiK6o=

KunYoRpk/1AWj5eFAuI4s/gP1ymxO++lT55n+K9qFIgN9O062n4n+aLvD9CaZULrgY44sFFyfE2tHZD6QN6qAcg00j2AhoC0WZHAytXKXfJnqQPvD75UAlkZhbnJy8jLvhLus7xazSxOdQpUvxlcT/JGwPM8Fn0Ow1/WKe1QHb1dSlU0FHicQtM0ZuLNXm4BiniSmtkYFqQnxcHfVHoyjuNXXPIVsMscan9pp6mff+XpRAu/NY21oYzS9dISCJ8wbY80hP872grI5HQYrnlbZ6wLUgAlIvJtafzkLNLvAyI=

5eUJ1sMkUpgXgDNmQmZTAQ==

let identity = function <T>(x: T): T {
  // ...
};

let reverse = function <U>(y: U): U {
  // ...
};

identity = reverse; // OK, because (x: any) => any matches (y: any) => any

高级主题

子类型与赋值

nWD6kBpqqoEdo1CziRRXv6OdPslfjVn+jPS5S3uWEeQB7u3HnvVT9ecHPiecxsb2hbLBr9mOKzpcv/6gGQT7i/B1WOP6aD7e2W0FyhLT4n7fiAAvWLv4n18afJn0yu6QNwEeGzb+THHBhjpH65DkotT2iT+ZPjL8QrlgOagt9fNdh1rG4uKT4b/A6OF4LQuelv5GgJTc1Gq/NCcENJr3+0Nphcr3KNP+rOvnS9TaI/nN7Vz4/RPNWhktx24R3T3bUa/a4+ZEYI0RaY4+kBRyFmVUdQ53EpRk6LN44lB/qBqNhKfXSUF1aSrDlr2ICpPbTJLEHt9YphfWZULrRtbyiK/4EZ727z8Cb1jVfQN+E753zrlbsYwH5E9ebCuP5G6kn3mcnkgl1cXC3R16pEvn5Ug0thSunPXDl9R2wiPdiIBE9ddQxjFlHTijv70F9ZEtYgV7kGXZI9hHRMhe76XN4ZnfIiqzy5Tul1z03jpwrbA=

TZpFFeCJuckNrv9ulCE573Ira1XgqAyABYzpwaGd4Y+y3+YQPetjctvqX8XC8MWntxE+w62hcz4swTxVev0iMeoUJU+lqbLI6rSqU16iHpYpMgI7Sd3/47lHqcdWFB9RIjrM4lJUC5LKVzImFkxpllyAK6NBNid4WhK+PLF6XZOKKpgbRpHnh+aiwW2JmPQ28noFjhTPuoKMxj1Bs/cWpjqB1gf5sBgbS5O+suID9F7uEwKxND0nGgeJRWkLHoST9xznTwivzANYGDXUEF4IJfE82x3ZVmAOfINWnsJqIMbf+9PHOcvsSG9hZAetbqtT

Any、unknown、object、void、undefined、null 和 never 可分配性

yCb3bahfWmCof54ZNvO3F5601z4s6cUy6Kyg/IaZwCrZOhGXma9y6SXWPzDFmd6bkhqHv67od27TGGGlWQCp3a2d2pjpCH7lvzq4zuqhOCbtc5yONs9jy+kn+kO3Q3SujmNmiQ41csou6B+0zXiEZBZYHaqdnVufq6TJnbe73YSZm39glTD/bh/i+l1gPhdA9vbCPScYrN+Y+eTodquuGHbazgP53c2s19yHPxofKfjdD/BdqqevxYJd595wSBI6c1pc5ADru1ODnDz0ZnfHRj0hkHDnothhXGnTOSuUoFaNEfH/L1ruil/WbcB3gMmDWYZa2xaTg+5YYImT59GpyutVbT+cEUH70/dRAG6H0TE=

anyunknown对象void未定义nullnever

AXYr290Q/tBX4xhOKSkBYA==

5GIrABVdN0cKvbqHpfcx6qERs7iVKpNpGP/Vh8Wgi7FaS+WtDJ07vZOa/sl2OqXaLhWclkY1Wzo3j5eF6vegFQ==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

/+149kECQFjsrkxG/pzjEg==

ecnQgjkR5bnP6Rc4XwEl5g==

kZd7xZem1h6JctBJ0SsBuA==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

0paKRKGzwL3rprEnZfkkgw==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

Er0m9c1bcoR5uG5gjw99LQ==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

/+149kECQFjsrkxG/pzjEg==

J3bfJ5yYv7YJ87KC1Mtu6g==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

/+149kECQFjsrkxG/pzjEg==

6uCzdqr1gXb0FevIl57+0A==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

/+149kECQFjsrkxG/pzjEg==

yw7699jVXkIKpPY51cyWvw==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

kZd7xZem1h6JctBJ0SsBuA==

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