ישנן שתי דרכים להגדיר טיפוסי נתונים ולהבחין ביניהם. הראשונה, והפשוטה יותר, היא להגדיר טיפוס כקבוצת הערכים אליה שייך כל משתנה מהטיפוס הזה. משתנה מטיפוס זה מייצג איבר מהקבוצה, כלומר מקבל אחד מהערכים השייכים לקבוצה. דרך זו מתאימה בעיקר לטיפוסים פשוטים, המתאימים לקבוצות מתמטיות מוכרות, כגון מספרים שלמים, מחרוזת וכדומה, ובאופן כללי לטיפוסים בהם יש התאמה חד-חד ערכית בין ערך של משתנה לייצוג של המשתנה ברמה נמוכה יותר, כגון שפת מכונה. הגדרה זו מתאימה פחות לטיפוסים מורכבים יותר, כגון שבר, בהם ניתן לייצג את אותו ערך בדרכים רבות. במקרה כזה אפילו פעולות פשוטות כגון השוואה או השמה, למשל, אינן טריוויאליות, ויש להגדיר אותן במפורש.
דרך שנייה היא להגדיר טיפוס כמימוש של מבנה נתונים מופשט, על ידי הפעולות המוגדרות עליו והסמנטיקה של פעולות אלו. דרך זו מתאימה במיוחד, אך לא באופן בלעדי, למחלקות בשפות תכנות מונחות-עצמים. דוגמה לטיפוס כזה היא מימוש של מחסנית.
מערכת הטיפוסים של שפת תכנות מאפשרת לאכוף ברמה זו או אחרת של נוקשות את הנכונות, העקביות והשלמות של השימוש בטיפוסי נתונים בשפה - למשל, כיצד משלבים משתנים בביטויים מורכבים - וכך להזהיר ולמנוע טעויות תכנות, להקל על קריאות התוכנית, להוכיח נכונות, ולהקל על המהדר לבצע אופטימיזציות.
טיפוסי מכונה.
ברמת שפת מכונה, אין "משמעות" לטיפוסי הנתונים, אלא רק ייצוג שלהם.
טיפוסים פרימיטיביים.
טיפוס נתונים פרימיטיבי הוא כינוי לטיפוס בסיסי הנתמך בשפה, להבדיל מטיפוס מורכב אותו השפה מאפשרת ליצור על ידי הרכבה של טיפוסים בסיסיים.
לכל שפת תכנות אוסף שונה של טיפוסים פרימיטיביים, המתאים לייעוד לשמו תוכננה השפה. ישנם טיפוסים הנתמכים בכל השפות או במרביתן, כגון מספר שלם (לעיתים ישנם מספר טיפוסים עבור מספר שלם במספר טווחי ערכים שונים, משיקולי יעילות), נקודה צפה המייצג בקירוב מספרים ממשיים, תו (ו\או מחרוזת), וטיפוס בוליאני המכיל שני ערכים - אמת ושקר.
טיפוסים פרימיטיביים נפוצים נוספים הם מצביע המאפשר לאחסן כתובת של משתנים, מספר מרוכב המסייע בביצוע חישובים פיזיקליים. בשפות תכנות המאפשרות תכנות פונקציונלי יש גם טיפוסים פרימיטיביים עבור פונקציה, ורשימה.
פרולוג היא חריגה בקרב שפות התכנות העיליות בכך שאין לה מערכת טיפוסים - כל הביטויים בשפה הם מאותו טיפוס פרימיטיבי, מושג (term).
שלמים.
טיפוס הנתונים הנפוץ הבסיסי ביותר לביצוע פעולות אריתמטיות הוא המספר השלם. טיפוס זה נתמך מבחינות רבות ישירות על ידי המעבד, על ידי פעולות חיבור, קידום באחד, הכפלה ב-2 או חלוקה ב-2 (על די פעולת "הזזה", shift) ועל פי רוב גם כפל וחילוק של שני מספרים כלשהם. בשל כך הפעולות על משתנים מטיפוס זה הן יעילות ביותר.
אף ייצוג במכונה לא יכול לאפשר אינסוף ערכים, כמו במספרים שלמים מתמטיים טהורים, ועל כן בזמן תכנון השפה או כתיבת מימוש לשפה (מהדר או מפרש) יש להחליט מהו טווח הערכים הרצוי. הבחירה הטבעית ביותר היא להשתמש בטווח המקסימלי הניתן לייצוג על ידי מילה במעבד הספציפי שבו מורצת התוכנית. בחירה כזאת משלבת תחום מספרים נרחב למדי יחד עם יעילות חישוב מקסימלית. עם זאת, הטווח עדיין מוגבל, והוא נעשה תלוי-מכונה - כלומר, תוכניות עלולות להתנהג שונה בהרצה על מחשבים שונים. אפשרות אחרת היא להגדיר מספר טיפוסים עבור מספר תחומים שונים, ולהשתמש בהם בהתאם לצורך. זה עשוי לבוא יחד עם התאמה למכונה (כמו בשפות C או ++C) או על ידי הגדרה חד משמעית של הטווח עבור כל טיפוס (כמו בשפת ג'אווה). אפשרות שלישית היא להגדיר טיפוס יחיד בעל טווח לא חסום, ולייצג אותו בצורה האופטימלית ביותר על פי הערך הנוכחי שלו (כמו בשפת פייתון החל מגרסה 3.0).
בנוסף לטווח הערכים, יש להחליט האם לייצג גם מספרים שליליים, או לייצג אך ורק מספרים טבעיים, ובכך להגדיל את הטווח פי 2 בקירוב). מספרים מטיפוס המאפשר מספרים טבעיים בלבד מיוצגים בזיכרון המחשב בייצוג בינארי פשוט. מספרים שליליים, לעומת זאת, מיוצגים באחת משתי השיטות משלים ל-2 או משלים ל-1.
נקודה צפה.
לצורך ייצוג של מספרים ממשיים משתמשים על פי רוב בייצוג של נקודה צפה. גם כאן יש חשיבות למספר הבתים בייצוג, כאשר השיקולים דומים לאלה שבמספרים ממשיים:
טיפוסי נתונים שאינם מספריים מיוצגים על ידי התאמת כל ערך למספר.
ערכי אמת.
ישנם שני ערכי אמת: "אמת" ו-"שקר". כדי לייצג ערך אמת מספיקה סיבית אחת, אך כיוון שלסיבית בודדת אין כתובת, לעיתים ערך אמת נשמר בבית או במילה. בשפות C ו ++C, הערך "שקר" מותאם לערך השלם 0, והערך "אמת" מותאם לשאר הערכים השלמים, אך לרוב מיוצג על ידי 1. בשפות מעטפת בלינוקס, כגון C Shell, המוסכמה היא הפוכה, בשל העבודה הצמודה עם תוכניות בלינוקס - שם מקובל שהערך 0 מייצג הצלחה, לעומת ערכים אי-שליליים המייצגים מספר שגיאה. בשפות אחרות, למשל Java, לא ניתן להחליף בין ערכים מספריים לערכי אמת, ואלו טיפוסים נפרדים לחלוטין. מכיוון שפעמים רבות מסתפקים רק בשימוש בערכים 0 או 1, ערכי אמת יכולים להיות מוגדרים ומיוצגים כמשתנים בוליאנים, ומכונים גם "דגל".
תווים.
תו (Character) הוא סימן גרפי כמו אות, ספרה, סימן פיסוק וכדומה. במרבית שפות התכנות קיים טיפוס תו, וממנו ניתן ליצור מילה (כמערך או רשימה של תווים).
בעבר תו נשמר בבית בודד (7 סיביות ומאוחר יותר 8 סיביות), בהתאמה לתקן Ascii. כיום רוב שפות התכנות שומרות תו בשני בתים בשיטת UTF-16.
בשפות ++C/C משתמשים בטיפוס char גם לצורך ייצוג של מספרים קטנים או כיחידה בסיסית המייצגת בית בודד, בשל העובדה שזהו הטיפוס הקטן ביותר בשפה, וכי מוגדר שגודלו הוא תמיד בית יחיד (בניגוד לטיפוסים אחרים שגודלם לא מוגדר באופן יחיד בתקן של השפה, והוא תלוי-מכונה ותלוי-מימוש).
יחידה.
טיפוס היחידה (unit) הוא טיפוס המכיל ערך אחד בלבד. אין צורך להבדיל בין סימון הערך לסימון הטיפוס כי ישנה התאמה חד-חד ערכית ביניהם. לביטוי שערכו הוא מטיפוס יחידה אין שימוש כחלק מביטוי אחר, ולכן הוא משמש רק לצורך השגת תוצאת הלוואי של הפעולה. טיפוס זה משמש על פי רוב בקריאה לפונקציה שכוללת תוצאת לוואי כגון פעולת פלט. פונקציה שמחזירה טיפוס כזה היא למעשה פרוצדורה.
בשפת ML הטיפוס נקרא unit ומסומן "()". בשפות ממשפחת ה-C הטיפוס נקרא void; בשפת פייתון הטיפוס נקרא NoneType וערכו נקרא None.
יש להבחין בין טיפוס שמכיל רק איבר בודד כערך לבין טיפוס השקול לקבוצה הריקה. טיפוס שהוא קבוצה ריקה פירושו שאין לו כל ערך קריאה לפונקציה ה"מחזירה" טיפוס כזה היא למעשה קריאה לפונקציה שאיננה חוזרת כלל (לדוגמה, פונקציית terminate המסיימת את פעולת התוכנית).
טיפוסי נתונים מורכבים.
רוב השפות המודרניות מאפשרות ליצור טיפוסי נתונים חדשים על ידי הרכבה של טיפוסים קיימים.
הדרך הפשוטה ביותר היא פשוט לתת שם חדש לטיפוס קיים (בשפת C, למשל, הפעולה הזאת מתבצעת על ידי ההצהרה typedef). פעולה כזאת תאפשר לשפר את קריאות התוכנית. לדוגמה, בשפת C (בתקן הראשון) אין טיפוס נתונים נפרד עבור ערכי אמת\שקר - מקביל לטיפוס Boolean בשפת פסקל. אם רוצים לדמות טיפוס כזה, אחת הדרכים היא להוסיף את ההצהרה
typedef int bool;
בהמשך התוכנית ניתן להציב ערכי אמת ושקר אל משתנים מטיפוס bool, וכך המטרה של משתנים אלה נעשית ברורה יותר למי שקורא את הקוד. ישנן שפות בהן הצהרה כזו היא פשוט הענקת שם חדש לטיפוס הקודם. בשפות אחרות הטיפוס החדש הוא טיפוס נפרד ולא ניתן להחליף בקלות פעולות על הטיפוס הישן עם פעולות על הטיפוס החדש.
רשימה.
בשפות תכנות המעודדות תכנות פונקציונלי, אחד הטיפוסים הפרימיטיביים הוא רשימה, שהיא למעשה רשימה מקושרת. משתנה מטיפוס "רשימה של תווים", למשל, עשוי להיות "רשימה ריקה" (מסומנת לרוב [] ומשותפת לכל סוגי הרשימות. מקבילה בערך לקבוצה ריקה במתמטיקה), או להכיל שני חלקים: ראש וזנב. כאשר הראש הוא האיבר הראשון ברשימה - למשל התו 'A' - והזנב הוא כל שאר הרשימה.
רשימה מקושרת כזאת נוחה מאוד לשימוש באלגוריתמים רקורסיביים, ובמקרים בהם מספר האיברים הסופי איננו ידוע מראש או משתנה. מימוש של רשימה כזאת איננו דורש מקום רצוף בזיכרון, איננו דורש הקצאה של זיכרון מראש, ומקל על איסוף זבל.
לעומת זאת, ישנם מקרים שבהם רשימה איננה מספיק טובה משיקולי סיבוכיות זמן ריצה. גישה לאיבר שרירותי באמצע רשימה (להבדיל ממעבר סדרתי מההתחלה לסוף או מהסוף להתחלה) גורר מעבר על כל אחד מאיברי הרשימה מההתחלה ועד אליו, בעוד שבמערך פעולה כזאת עשויה להתבצע בפעולת מעבד יחידה. עם זאת, שפות פונקציונליות מתקשות לספק תמיכה במערכים בשל שיקולים של הקצאת זיכרון ואיסוף זבל.
מערך.
במרבית שפות התכנות, מערך הוא רצף של משתנים מאותו טיפוס, בגודל מסוים. גישה למשתנה ספציפי במערך מתבצעת באמצעות אינדקס - על פי רוב מספר, או משתנה דיסקרטי אחר (תו, Enum וכדומה). על פי רוב גודל המערך הוא קבוע, בשל היעילות הנגזרת מכך: במערך שמאוחסן בזיכרון המחשב באופן רציף (וזה המימוש הנפוץ), גישה למשתנה ספציפי - למשל אל האיבר השלישי - מתבצעת תמיד תוך מספר פעולות חסום, ולעיתים בפקודת מכונה בודדת. על מנת לאפשר הגדלה של מערך תוך שמירה על תכונה זו יש צורך למצוא ולהקצות זיכרון רצוף בגודל החדש, ולהעתיק את כל האיברים הקיימים במערך - פעולות שעשויות להיות יקרות למדי. עם זאת, בשפות תכנות מודרניות ישנם מערכים המאפשרים ביצוע פעולות כאלה, כשלרוב הסיבוכיות בפועל (בניגוד לסיבוכיות התאורטית) זניחה.
Tuple.