I am wondering if it is possible given a file with an exported type, could the types be extracted from the generic, to a computed type?
function example() {
return {
foo: 'hi',
bar: true,
baz: 1
};
}
export type Signature = ReturnType<typeof example>;
To this:
export type Signature = {
foo: string;
bar: boolean;
baz: number;
}
I don't believe that the tsc
cli does this, and I'm not sure what this process would be called.
Can tsc
create this export?
Are there any third-party tools that can do this?
The only way I know how to do this is hover over the variable in VSCode and copy the computed type, and that only works if it's short, and doesn't trail off ...
I found some other references to similar requests:
The exported types can be imported by using a named import as import {A, B} from './another-file'. You can have as many named exports as necessary in a single file.
Use a named export to export a type in TypeScript, e.g. export type Person = {}. The exported type can be imported by using a named import as import {Person} from './another-file'. You can have as many named exports as necessary in a single file. Here is an example of exporting a type from a file called another-file.ts.
The Export Delivery Methods screen displays. Provide the following information and select the OK button. File Type. Name of the export. To create a new file type, select New from the Export File List and enter a new file type name for the export.
You can manually create export files as needed or in case the End of Day routine procedure did not produce the desired export. To do so, select Miscellaneous>File Export>General (Sales and Catering exports, Country exports, Memberships exports, Commission exports and other types of exports are available based on parameter settings or licenses).
Looking into this question, without replicating VSCode's hover.ts
, I find that one, if not the only, answer to this question is:
tsserver
You need to communicate the line and char offset in your file to the server. One should be able to use abstract syntax tree (AST) in .ts
for that. I wrote a client in bash instead. Attached below, it supports calculating char offset from column (as seen in the VSCode statusbar). A log from a run of your source and a document position on the word "Signature" follows and the end comes very close to your wanted extraction.
$ (prepared=('open -s #.ts -i file' 'quickinfo -s #.ts -i file -n 9 -i line -n 20 -i _column_')&&. $(which tsssh))
ts < open -s #.ts -i file
{"seq": 1, "type": "request", "command": "open", "arguments": {"file": "#.ts"}}
ts < quickinfo -s #.ts -i file -n 9 -i line -n 20 -i _column_
{"seq": 1, "type": "request", "command": "quickinfo", "arguments": {"file": "#.ts", "line": 9, "offset": 19}}
event #0
event: typingsInstallerPid
body: {"pid": 65341}
response #0 (1)
command: quickinfo
body: {"kind": "type", "kindModifiers": "export", "start": {"line": 9, "offset": 13}, "end": {"line": 9, "offset": 22}, "displayString": "type Signature = {\n foo: string;\n bar: boolean;\n baz: number;\n}", "documentation": "", "tags": []}
displayString: type Signature = {
foo: string;
bar: boolean;
baz: number;
}
bash -O cmdhist -O lithist
with macports, and various other shopt..tsserver=./node_modules/typescript/bin/tsserver tsssh
..histfile= path/to/tsssh
. Multiple "prepared" can be specified as (prepared=("first" ... "last")&&. path/to/tsssh)
#!/usr/bin/env bash
( # Quick and dirty client for https://github.com/Microsoft/TypeScript/wiki/Standalone-Server-%28tsserver%29..
# Relies heavily on prerequisite http://kmkeen.com/jshon/, and compatible bash and gawk, while tput and tee could be cut out I guess..
# Developed on macOS 10.13.6 in version 5.0.16 `bash -O cmdhist -O lithist` with macports, and various other shopt..
# NB: You need to poll event/response manually by sending empty commandlines. Exit with kill -sigint , typically ctrl+C..
# Run in local repo like `tsserver=./node_modules/typescript/bin/tsserver tsssh`..
# Disable history with `histfile='' path/to/tsssh`. Multiple "prepared" can be specified as `(prepared=("first" ... "last")&&. path/to/tsssh)`
# Copyright 2020 Viktor Bergquist ([email protected]), license https://creativecommons.org/licenses/by-sa/4.0/
HISTFILE=${histfile-.tsssh_history} &&
{ ((\!-( x = xtrace )))||set -x ;} && ((!errexit))||set -e &&
state()(set +x;tput setaf $1;echo "${*:2}";tput sgr0;((\!-x))||set -x) >&2 && trap 'state 1 $?: "$BASH_COMMAND"' err &&
[[ ! $HISTFILE ]]||{ h=$HISTSIZE&&HISTSIZE=1&&set -o history&&HISTSIZE=$h&&history -s ''&&{ history -r "$HISTFILE"||:;};}&&
coproc ts (${tsserver:-tsserver}) &&set -o pipefail&&command sleep 1 &&
show(){ set +x; f=$1&&shift && i=$(cat) && declare -n n&&for n;do
n=$(((\!-x))||set -x; jshon <<<"$i" -e "${!n}" $f);((e=$?)) || echo "${!n}: $n"; done; ((\!-x))||set -x; return $e;} &&
extract(){ show "$@";} >/dev/null &&
compact()( "$@"|gawk -vORS= '{sub("^\\s+",!m[0]?"":" ")}1;{match($0,",$",m)}END{printf"\n"}') &&
function check(){ while {
read -rt.1 -d$'\r' h&&[[ $h =~ Content-Length:\ ([0-9]+) ]]&&read -r$t -N3&&read -r$t -N$((${BASH_REMATCH[1]}-1)) a;} <&${ts[0]};do
#set +x;echo 'ts > '"$a";((\!-x))||set -x
<<<"$a" extract -u type seq &&case $type in
( event)state 2 $type \#$seq
<<<"$a" show -u event ;;&
(response)<<<"$a" extract -u success request_seq&&case $success in
( false)state 1 $type \#$seq "($request_seq)"
<<<"$a" show -u command message ;;
( true)state 2 $type \#$seq "($request_seq)"
<<<"$a" show -u command message metadata 2>/dev/null ;;
( *)state 1 "unknown success: $success" ;esac ;&
( event)<<<"$a" compact show '' body ;! [[ $type = response && $success = true ]]||case $command in
( *)<<<"$a" extract '' body ;;&
( quickinfo) <<< "$body" show -u displayString ;esac ;;
( *)state 1 "unknown type: $type" ;esac ;done;} &&
seq=0 && for p in ${!prepared[@]} -1;do for fd in <(echo "${prepared[p]}") 0;do fd="${fd##*/}"; (((p<0)!=(0<fd)))||continue
while check <&-; set +x; read -p 'ts < ' -era Q; do
((\!${#Q[*]}))&&{ tput -S<<<$'cuu1\nel'
((\!-x))||set -x;} ||
{ ((\!-x))||set -x
history -s "${Q[*]}"&&{ [[ ! $HISTFILE ]]||{ [[ ! -a $HISTFILE ]]&&history -w "$HISTFILE"||history -a "$HISTFILE";};} &&
d=$(compact jshon <<<{} -n$((++seq)) -i seq -s request -i type -s "$Q" -i command -n {} "${Q[@]:1}" -i arguments)
A=$(compact jshon <<<{} "${Q[@]:1}")
! <<<"$A" extract -u file line _column_ 2>/dev/null ||
{ o=$(gawk -vT="${tabs:-4}" -vC="$_column_" FNR=="$line"'{
t=-1;for(o=0;o<=length();o++){t++;if("\t"==substr($0,o,1)){t+=T-1;t-=t%T}if(t>=C)break}print o-1
}' "$file") &&
d=$(<<<"$d" compact jshon -e arguments -d _column_ -n "$o" -i offset -p);}
tee <<<"$d" /dev/stderr >&${ts[1]};}
done<&$fd;done;done;set +x;echo bye) #ts < eg: reload -s index.ts -i file ^M quickinfo -s index.ts -i file -n 4 -i line -n 7 -i _column_
With all your question's good references, you surely know some "trail off" that you mention can be prevented with "compilerOptions":{"noErrorTruncation":true}
in the tsconfig.json
:)
To the end of those references I can add that there's also an Interactive Diagnostics PR 31384 (draft) to hope for :)
For the time being I'll look into the interesting utility type in the related Q&A How can I see the full expanded contract of a Typescript type?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With