Không có bất kỳ cơ chế tích hợp nào trong bản thảo để đăng xuất thông tin mong muốn được đề cập. Tuy nhiên, nếu bạn quan tâm đến việc tìm hiểu công việc nội bộ, thì đây là vị trí trong mã nguồn nơi thực sự giải quyết các loại điều kiện.
Hãy nhìn vào những nơi này checker.ts
.
ln: 13258 instantiateTypeWorker()
ln: 12303 getConditionalType()
ln: 12385 getTypeFromConditionalTypeNode()
ln: 12772getTypeFromTypeNode()
Kèm theo là một plugin kiểu chữ được thực hiện một nửa tôi bất cẩn kết hợp. Nó đăng xuất cấu trúc dữ liệu thô của a ConditionalType
. Để hiểu cấu trúc này, hãy kiểm tra các loại.ts ln: 4634.
UX của plugin này rất tệ, nhưng cấu trúc đó cho bạn biết cách bản thảo quyết định giá trị cuối cùng của một loại điều kiện.
import stringify from "fast-safe-stringify";
function init(modules: {
typescript: typeof import("typescript/lib/tsserverlibrary");
}) {
const ts = modules.typescript;
// #region utils
function replacer(name, val) {
if (name === "checker" || name === "parent") {
return undefined;
}
return val;
}
function getContainingObjectLiteralElement(node) {
var element = getContainingObjectLiteralElementWorker(node);
return element &&
(ts.isObjectLiteralExpression(element.parent) ||
ts.isJsxAttributes(element.parent))
? element
: undefined;
}
ts.getContainingObjectLiteralElement = getContainingObjectLiteralElement;
function getContainingObjectLiteralElementWorker(node) {
switch (node.kind) {
case 10 /* StringLiteral */:
case 14 /* NoSubstitutionTemplateLiteral */:
case 8 /* NumericLiteral */:
if (node.parent.kind === 153 /* ComputedPropertyName */) {
return ts.isObjectLiteralElement(node.parent.parent)
? node.parent.parent
: undefined;
}
// falls through
case 75 /* Identifier */:
return ts.isObjectLiteralElement(node.parent) &&
(node.parent.parent.kind === 192 /* ObjectLiteralExpression */ ||
node.parent.parent.kind === 272) /* JsxAttributes */ &&
node.parent.name === node
? node.parent
: undefined;
}
return undefined;
}
function getPropertySymbolsFromContextualType(
node,
checker,
contextualType,
unionSymbolOk
) {
var name = ts.getNameFromPropertyName(node.name);
if (!name) return ts.emptyArray;
if (!contextualType.isUnion()) {
var symbol = contextualType.getProperty(name);
return symbol ? [symbol] : ts.emptyArray;
}
var discriminatedPropertySymbols = ts.mapDefined(
contextualType.types,
function(t) {
return ts.isObjectLiteralExpression(node.parent) &&
checker.isTypeInvalidDueToUnionDiscriminant(t, node.parent)
? undefined
: t.getProperty(name);
}
);
if (
unionSymbolOk &&
(discriminatedPropertySymbols.length === 0 ||
discriminatedPropertySymbols.length === contextualType.types.length)
) {
var symbol = contextualType.getProperty(name);
if (symbol) return [symbol];
}
if (discriminatedPropertySymbols.length === 0) {
// Bad discriminant -- do again without discriminating
return ts.mapDefined(contextualType.types, function(t) {
return t.getProperty(name);
});
}
return discriminatedPropertySymbols;
}
ts.getPropertySymbolsFromContextualType = getPropertySymbolsFromContextualType;
function getNodeForQuickInfo(node) {
if (ts.isNewExpression(node.parent) && node.pos === node.parent.pos) {
return node.parent.expression;
}
return node;
}
// #endregion
/**
* plugin code starts here
*/
function create(info: ts.server.PluginCreateInfo) {
const log = (s: any) => {
const prefix =
">>>>>>>> [TYPESCRIPT-FOOBAR-PLUGIN] <<<<<<<< \n";
const suffix = "\n<<<<<<<<<<<";
if (typeof s === "object") {
s = stringify(s, null, 2);
}
info.project.projectService.logger.info(prefix + String(s) + suffix);
};
// Diagnostic logging
log("PLUGIN UP AND RUNNING");
// Set up decorator
const proxy: ts.LanguageService = Object.create(null);
for (let k of Object.keys(info.languageService) as Array<
keyof ts.LanguageService
>) {
const x = info.languageService[k];
proxy[k] = (...args: Array<{}>) => x.apply(info.languageService, args);
}
proxy.getQuickInfoAtPosition = (filename, position) => {
var program = ts.createProgram(
[filename],
info.project.getCompilerOptions()
);
var sourceFiles = program.getSourceFiles();
var sourceFile = sourceFiles[sourceFiles.length - 1];
var checker = program.getDiagnosticsProducingTypeChecker();
var node = ts.getTouchingPropertyName(sourceFile, position);
var nodeForQuickInfo = getNodeForQuickInfo(node);
var nodeType = checker.getTypeAtLocation(nodeForQuickInfo);
let res;
if (nodeType.flags & ts.TypeFlags.Conditional) {
log(stringify(nodeType, replacer, 2));
}
if (!res)
res = info.languageService.getQuickInfoAtPosition(filename, position);
return res;
};
return proxy;
}
return { create };
}
export = init;
Một số hướng dẫn chi tiết gây khó chịu để chạy plugin này:
mkdir my-ts-plugin && cd my-ts-plugin
touch package.json
và viết { "name": "my-ts-plugin", "main": "index.js" }
yarn add typescript fast-safe-stringify
- sao chép-dán đoạn mã này vào
index.ts
, sử dụng tsc để biên dịch nó thànhindex.js
yarn link
- bây giờ
cd
đến thư mục dự án ts của riêng bạn, chạyyarn link my-ts-plugin
- thêm
{ "compilerOptions": { "plugins": [{ "name": "my-ts-plugin" }] } }
vào của bạntsconfig.json
- thêm vào không gian làm việc thiết lập
(.vscode/settings.json)
dòng này:{ "typescript.tsdk": "<PATH_TO_YOUR_TS_PROJECT>/node_modules/typescript/lib" }
- mở bảng lệnh vscode và chạy:
TypeScript: Select TypeScript Version... -> Use Workspace Version
TypeScript: Restart TS Server
TypeScript: Open TS Server Log
- bạn sẽ có thể thấy đăng xuất plugin
"PLUGIN UP AND RUNNING"
, bây giờ hãy mở tệp mã ts và di chuột đến một nút loại có điều kiện, bạn sẽ thấy cấu trúc dữ liệu loooooong json được thêm vào tệp nhật ký.