\charcode is undefined.
I suppose you wish to use \catcode.
Never give a macro a name that begins with \if like \ifletter.
You will quickly reach a point where you cannot distingush such macros from TeX's \if...-primitives and things defined in terms of \newif.
But instances of macros on the one side and instances of \if..-primitives/\newif-thingies on the other side need to be distinguished from each other because instances of TeX's \if...-primitives and \newif-thingies are taken into account when TeX with \if..\else..\fi-branching does its \if..\else..\fi-matching while instances of macros are not taken into account there.
So if you don't stick to the convention of only giving \if..-primitives/\newif-thingies names that begin with \if.., you might easily be confused about what is/is not taken into account by TeX's \if..\else..\fi-matching.
If you really wish to find out whether a specific character currently is assigned the category code 11—which actually is an information about the behavior of TeX's reading- and tokenizing-apparatus and is not an information about properties of a token that already exists—so that TeX in the future will create an explicit character token of category 11(letter) when encountering an instance of that character while reading from the .tex-input-file and creating tokens from the characters just read, you can do so via \ifnum\the\catcode`#1=11 ... \else ... \fi whereby #1 is an alphabetic constant, i.e., either a one-letter-control-sequence or an explicit character token.
But this check does only tell you something about how currently the reading- and tokenizing-apparatus is adjusted, namely about the categories which explicit character tokens will have when coming into being by tokenizing subsequent instances of the character in question while reading and tokenizing the .tex-input file.
This check does not tell you something about properties of character tokens that already exist. This check does not tell you which category an already tokenized character token has.
In order to find out about the latter you can use \ifcat.
If you wish to test whether an already tokenized explicit character-token is of category 11(letter), and you can rely on TeX's default-settings for category codes and thus can rely on category code 11(letter) being assigned to the character A, so that characters A in the .tex-input file will be tokenized as explicit character tokens of category 11(letter) you can do something like this:
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
\def\CheckWhetherTokenOfletterCategory#1{%
\ifcat A\noexpand#1\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
}%
\newlinechar=`^^J
\message{^^JThe token + \CheckWhetherTokenOfletterCategory{+}{is}{is not} of category 11(letter).}
\message{^^JThe token $ \CheckWhetherTokenOfletterCategory{$}{is}{is not} of category 11(letter).}
\message{^^JThe token A \CheckWhetherTokenOfletterCategory{A}{is}{is not} of category 11(letter).}
\bye
(When it comes to forking/branching I often do the \expandafter\firstoftwo/\expandafter\secondoftwo-trick because this way the user-provided argument does not occur within the \if..\else..\fi-expression. User-provided arguments occurring within \if..\else..\fi-expressions might cause problems with proper \if..\else..\fi-matching in case the user-provided argument contains unbalanced \if.. or \else or \fi-tokens or the like.)
If for some reason you cannot rely on TeX's default-settings for category codes and thus cannot rely on category code 11(letter) being assigned to character A and thus cannot rely on explicit character tokens that come into being while tokenizing the input-character A being of category 11(letter), you can adjust the category-code-régime within a local scope before having TeX read the argument from the .tex-file and tokenize it:
\begingroup
% Within the local scope/group do adjustments to the reading- and
% tokenizing-apparatus, i.e., adjustments to the category-code-régime,
% adjustments to the parameter `\endlinechar`:
\def\firstofone#1{#1}%
\catcode`\A=11 %<-Just to make sure...
\firstofone{% \firstofone ensures tokenization of its argument while
% catcode-changes etc introduced within the local scope/
% group are in effect. Then in the gullet the
% replacement of \firstofone , i.e., the set of tokens
% that forms the argument, is delivered. It contains the
% token \endgroup which makes it into the stomach and
% ends the group so that catcode-changes etc are not in
% effect any more when tokenizing stuff that follows
% \firstofone's argument.
\endgroup
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
\def\CheckWhetherTokenOfletterCategory#1{%
\ifcat A\noexpand#1\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
}%
}%
\newlinechar=`\^^J
\message{^^JThe token + \CheckWhetherTokenOfletterCategory{+}{is}{is not} of category 11(letter).}
\message{^^JThe token $ \CheckWhetherTokenOfletterCategory{$}{is}{is not} of category 11(letter).}
\message{^^JThe token A \CheckWhetherTokenOfletterCategory{A}{is}{is not} of category 11(letter).}
\bye
Console output:
The token + is not of category 11(letter).
The token $ is not of category 11(letter).
The token A is of category 11(letter).
If you really need to know which which category explicit character tokens will have when coming into being due to tokenizing subsequent instances of the character in question while reading and tokenizing the .tex-input file, I suggest doing something like this:
\long\def\firstoftwo#1#2{#1}%
\long\def\secondoftwo#1#2{#2}%
\def\getCurrentCategoryCode#1{\the\catcode`#1}
\def\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter#1{%
\ifnum\getCurrentCategoryCode{#1}=11 %
\expandafter\firstoftwo\else\expandafter\secondoftwo\fi
}%
% Without \getcatcode:
%
%\def\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter#1{%
% \ifnum\the\catcode`#1=11 %
% \expandafter\firstoftwo\else\expandafter\secondoftwo\fi
%}%
\newlinechar=`\^^J
\message{^^J\getCurrentCategoryCode{#}}
\message{^^J\getCurrentCategoryCode{-}}
\message{^^J\getCurrentCategoryCode{+}}
\message{^^J\getCurrentCategoryCode{\%}}
\message{^^J\getCurrentCategoryCode{\\}}
\message{^^J\getCurrentCategoryCode{\{}}
\message{^^J\getCurrentCategoryCode{\}}}
\message{^^J\getCurrentCategoryCode{A}}
\message{^^JSubsequent instances of the hash-character occurring in the .tex-input-file will
\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter{#}{be}{not be} tokenized as explicit character tokens of letter category.}
\message{^^JSubsequent instances of the character - occurring in the .tex-input-file will
\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter{-}{be}{not be} tokenized as explicit character tokens of letter category.}
\message{^^JSubsequent instances of the character + occurring in the .tex-input-file will
\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter{+}{be}{not be} tokenized as explicit character tokens of letter category.}
\message{^^JSubsequent instances of the percent-character occurring in the .tex-input-file will
\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter{\%}{be}{not be} tokenized as explicit character tokens of letter category.}
\message{^^JSubsequent instances of the backslash character occurring in the .tex-input-file will
\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter{\\}{be}{not be} tokenized as explicit character tokens of letter category.}
\message{^^JSubsequent instances of the curly left brace occurring in the .tex-input-file will
\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter{\{}{be}{not be} tokenized as explicit character tokens of letter category.}
\message{^^JSubsequent instances of the curly right brace occurring in the .tex-input-file will
\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter{\}}{be}{not be} tokenized as explicit character tokens of letter category.}
\message{^^JSubsequent instances of the character A occurring in the .tex-input-file will
\AtIfSubsequentlyTokenizedCharactersWillHaveCategoryLetter{A}{be}{not be} tokenized as explicit character tokens of letter category.}
\bye
Console output:
6
12
12
14
0
1
2
11
Subsequent instances of the hash-character occurring in the .tex-input-file wil
l not be tokenized as explicit character tokens of letter category.
Subsequent instances of the character - occurring in the .tex-input-file will n
ot be tokenized as explicit character tokens of letter category.
Subsequent instances of the character + occurring in the .tex-input-file will n
ot be tokenized as explicit character tokens of letter category.
Subsequent instances of the percent-character occurring in the .tex-input-file
will not be tokenized as explicit character tokens of letter category.
Subsequent instances of the backslash character occurring in the .tex-input-fil
e will not be tokenized as explicit character tokens of letter category.
Subsequent instances of the curly left brace occurring in the .tex-input-file w
ill not be tokenized as explicit character tokens of letter category.
Subsequent instances of the curly right brace occurring in the .tex-input-file
will not be tokenized as explicit character tokens of letter category.
Subsequent instances of the character A occurring in the .tex-input-file will b
e tokenized as explicit character tokens of letter category.
charcode, notcatcode. Which one are you trying to retrieve? For the catcode,\def\getcatcode#1{\the\catcode`#1 }should do – Phelype Oleinik Sep 08 '22 at 00:18